19a747e4fSDavid du Colombier #include "dat.h" 29a747e4fSDavid du Colombier 39a747e4fSDavid du Colombier static char secstore[100]; /* server name */ 49a747e4fSDavid du Colombier 59a747e4fSDavid du Colombier /* bind in the default network and cs */ 69a747e4fSDavid du Colombier static int 79a747e4fSDavid du Colombier bindnetcs(void) 89a747e4fSDavid du Colombier { 99a747e4fSDavid du Colombier int srvfd; 109a747e4fSDavid du Colombier 11d9306527SDavid du Colombier if(access("/net/tcp", AEXIST) < 0) 129a747e4fSDavid du Colombier bind("#I", "/net", MBEFORE); 139a747e4fSDavid du Colombier 149a747e4fSDavid du Colombier if(access("/net/cs", AEXIST) < 0){ 159a747e4fSDavid du Colombier if((srvfd = open("#s/cs", ORDWR)) >= 0){ 169a747e4fSDavid du Colombier if(mount(srvfd, -1, "/net", MBEFORE, "") >= 0) 179a747e4fSDavid du Colombier return 0; 189a747e4fSDavid du Colombier close(srvfd); 199a747e4fSDavid du Colombier } 209a747e4fSDavid du Colombier return -1; 219a747e4fSDavid du Colombier } 229a747e4fSDavid du Colombier return 0; 239a747e4fSDavid du Colombier } 249a747e4fSDavid du Colombier 259a747e4fSDavid du Colombier int 269a747e4fSDavid du Colombier _authdial(char *net, char *authdom) 279a747e4fSDavid du Colombier { 289a747e4fSDavid du Colombier int fd; 299a747e4fSDavid du Colombier int vanilla; 309a747e4fSDavid du Colombier 319a747e4fSDavid du Colombier vanilla = net==nil || strcmp(net, "/net")==0; 329a747e4fSDavid du Colombier 339a747e4fSDavid du Colombier if(!vanilla || bindnetcs()>=0) 349a747e4fSDavid du Colombier return authdial(net, authdom); 359a747e4fSDavid du Colombier 369a747e4fSDavid du Colombier /* use the auth sever passed to us as an arg */ 379a747e4fSDavid du Colombier if(authaddr == nil) 389a747e4fSDavid du Colombier return -1; 399a747e4fSDavid du Colombier fd = dial(netmkaddr(authaddr, "il", "566"), 0, 0, 0); 409a747e4fSDavid du Colombier if(fd >= 0) 419a747e4fSDavid du Colombier return fd; 429a747e4fSDavid du Colombier return dial(netmkaddr(authaddr, "tcp", "567"), 0, 0, 0); 439a747e4fSDavid du Colombier } 449a747e4fSDavid du Colombier 459a747e4fSDavid du Colombier int 469a747e4fSDavid du Colombier secdial(void) 479a747e4fSDavid du Colombier { 489a747e4fSDavid du Colombier char *p, buf[80], *f[3]; 499a747e4fSDavid du Colombier int fd, nf; 509a747e4fSDavid du Colombier 519a747e4fSDavid du Colombier p = secstore; /* take it from writehostowner, if set there */ 529a747e4fSDavid du Colombier if(*p == 0) /* else use the authserver */ 539a747e4fSDavid du Colombier p = "$auth"; 549a747e4fSDavid du Colombier 559a747e4fSDavid du Colombier if(bindnetcs() >= 0) 569a747e4fSDavid du Colombier return dial(netmkaddr(p, "net", "secstore"), 0, 0, 0); 579a747e4fSDavid du Colombier 589a747e4fSDavid du Colombier /* translate $auth ourselves. 599a747e4fSDavid du Colombier * authaddr is something like il!host!566 or tcp!host!567. 609a747e4fSDavid du Colombier * extract host, accounting for a change of format to something 619a747e4fSDavid du Colombier * like il!host or tcp!host or host. 629a747e4fSDavid du Colombier */ 639a747e4fSDavid du Colombier if(strcmp(p, "$auth")==0){ 649a747e4fSDavid du Colombier if(authaddr == nil) 659a747e4fSDavid du Colombier return -1; 669a747e4fSDavid du Colombier safecpy(buf, authaddr, sizeof buf); 679a747e4fSDavid du Colombier nf = getfields(buf, f, nelem(f), 0, "!"); 689a747e4fSDavid du Colombier switch(nf){ 699a747e4fSDavid du Colombier default: 709a747e4fSDavid du Colombier return -1; 719a747e4fSDavid du Colombier case 1: 729a747e4fSDavid du Colombier p = f[0]; 739a747e4fSDavid du Colombier break; 749a747e4fSDavid du Colombier case 2: 759a747e4fSDavid du Colombier case 3: 769a747e4fSDavid du Colombier p = f[1]; 779a747e4fSDavid du Colombier break; 789a747e4fSDavid du Colombier } 799a747e4fSDavid du Colombier } 809a747e4fSDavid du Colombier fd = dial(netmkaddr(p, "tcp", "5356"), 0, 0, 0); 819a747e4fSDavid du Colombier if(fd >= 0) 829a747e4fSDavid du Colombier return fd; 839a747e4fSDavid du Colombier return -1; 849a747e4fSDavid du Colombier } 859a747e4fSDavid du Colombier /* 869a747e4fSDavid du Colombier * prompt user for a key. don't care about memory leaks, runs standalone 879a747e4fSDavid du Colombier */ 889a747e4fSDavid du Colombier static Attr* 899a747e4fSDavid du Colombier promptforkey(char *params) 909a747e4fSDavid du Colombier { 919a747e4fSDavid du Colombier char *v; 929a747e4fSDavid du Colombier int fd; 939a747e4fSDavid du Colombier Attr *a, *attr; 949a747e4fSDavid du Colombier char *def; 959a747e4fSDavid du Colombier 969a747e4fSDavid du Colombier fd = open("/dev/cons", ORDWR); 979a747e4fSDavid du Colombier if(fd < 0) 989a747e4fSDavid du Colombier sysfatal("opening /dev/cons: %r"); 999a747e4fSDavid du Colombier 1009a747e4fSDavid du Colombier attr = _parseattr(params); 1019a747e4fSDavid du Colombier fprint(fd, "\n!Adding key:"); 1029a747e4fSDavid du Colombier for(a=attr; a; a=a->next) 1032ebbfa15SDavid du Colombier if(a->type != AttrQuery && a->name[0] != '!') 1042ebbfa15SDavid du Colombier fprint(fd, " %q=%q", a->name, a->val); 1059a747e4fSDavid du Colombier fprint(fd, "\n"); 1069a747e4fSDavid du Colombier 1079a747e4fSDavid du Colombier for(a=attr; a; a=a->next){ 1082ebbfa15SDavid du Colombier v = a->name; 1099a747e4fSDavid du Colombier if(a->type != AttrQuery || v[0]=='!') 1109a747e4fSDavid du Colombier continue; 1119a747e4fSDavid du Colombier def = nil; 1129a747e4fSDavid du Colombier if(strcmp(v, "user") == 0) 1139a747e4fSDavid du Colombier def = getuser(); 1149a747e4fSDavid du Colombier a->val = readcons(v, def, 0); 1159a747e4fSDavid du Colombier if(a->val == nil) 1169a747e4fSDavid du Colombier sysfatal("user terminated key input"); 1179a747e4fSDavid du Colombier a->type = AttrNameval; 1189a747e4fSDavid du Colombier } 1199a747e4fSDavid du Colombier for(a=attr; a; a=a->next){ 1202ebbfa15SDavid du Colombier v = a->name; 1219a747e4fSDavid du Colombier if(a->type != AttrQuery || v[0]!='!') 1229a747e4fSDavid du Colombier continue; 1239a747e4fSDavid du Colombier def = nil; 1249a747e4fSDavid du Colombier if(strcmp(v+1, "user") == 0) 1259a747e4fSDavid du Colombier def = getuser(); 1269a747e4fSDavid du Colombier a->val = readcons(v+1, def, 1); 1279a747e4fSDavid du Colombier if(a->val == nil) 1289a747e4fSDavid du Colombier sysfatal("user terminated key input"); 1299a747e4fSDavid du Colombier a->type = AttrNameval; 1309a747e4fSDavid du Colombier } 1319a747e4fSDavid du Colombier fprint(fd, "!\n"); 1329a747e4fSDavid du Colombier close(fd); 1339a747e4fSDavid du Colombier return attr; 1349a747e4fSDavid du Colombier } 1359a747e4fSDavid du Colombier 1369a747e4fSDavid du Colombier /* 1379a747e4fSDavid du Colombier * send a key to the mounted factotum 1389a747e4fSDavid du Colombier */ 1399a747e4fSDavid du Colombier static int 1409a747e4fSDavid du Colombier sendkey(Attr *attr) 1419a747e4fSDavid du Colombier { 1429a747e4fSDavid du Colombier int fd, rv; 1439a747e4fSDavid du Colombier char buf[1024]; 1449a747e4fSDavid du Colombier 1459a747e4fSDavid du Colombier fd = open("/mnt/factotum/ctl", ORDWR); 1469a747e4fSDavid du Colombier if(fd < 0) 1479a747e4fSDavid du Colombier sysfatal("opening /mnt/factotum/ctl: %r"); 1489a747e4fSDavid du Colombier rv = fprint(fd, "key %A\n", attr); 1499a747e4fSDavid du Colombier read(fd, buf, sizeof buf); 1509a747e4fSDavid du Colombier close(fd); 1519a747e4fSDavid du Colombier return rv; 1529a747e4fSDavid du Colombier } 1539a747e4fSDavid du Colombier 1549a747e4fSDavid du Colombier /* askuser */ 1559a747e4fSDavid du Colombier void 1569a747e4fSDavid du Colombier askuser(char *params) 1579a747e4fSDavid du Colombier { 1589a747e4fSDavid du Colombier Attr *attr; 1599a747e4fSDavid du Colombier 1609a747e4fSDavid du Colombier attr = promptforkey(params); 1619a747e4fSDavid du Colombier if(attr == nil) 1629a747e4fSDavid du Colombier sysfatal("no key supplied"); 1639a747e4fSDavid du Colombier if(sendkey(attr) < 0) 1649a747e4fSDavid du Colombier sysfatal("sending key to factotum: %r"); 1659a747e4fSDavid du Colombier } 1669a747e4fSDavid du Colombier 1679a747e4fSDavid du Colombier ulong conftaggen; 1689a747e4fSDavid du Colombier int 1699a747e4fSDavid du Colombier canusekey(Fsstate *fss, Key *k) 1709a747e4fSDavid du Colombier { 1719a747e4fSDavid du Colombier int i; 1729a747e4fSDavid du Colombier 1732ebbfa15SDavid du Colombier if(_strfindattr(k->attr, "confirm")){ 1749a747e4fSDavid du Colombier for(i=0; i<fss->nconf; i++) 1759a747e4fSDavid du Colombier if(fss->conf[i].key == k) 1769a747e4fSDavid du Colombier return fss->conf[i].canuse; 1779a747e4fSDavid du Colombier if(fss->nconf%16 == 0) 1789a747e4fSDavid du Colombier fss->conf = erealloc(fss->conf, (fss->nconf+16)*(sizeof(fss->conf[0]))); 1799a747e4fSDavid du Colombier fss->conf[fss->nconf].key = k; 1809a747e4fSDavid du Colombier k->ref++; 1819a747e4fSDavid du Colombier fss->conf[fss->nconf].canuse = -1; 1829a747e4fSDavid du Colombier fss->conf[fss->nconf].tag = conftaggen++; 1839a747e4fSDavid du Colombier fss->nconf++; 1849a747e4fSDavid du Colombier return -1; 1859a747e4fSDavid du Colombier } 1869a747e4fSDavid du Colombier return 1; 1879a747e4fSDavid du Colombier } 1889a747e4fSDavid du Colombier 1899a747e4fSDavid du Colombier /* closekey */ 1909a747e4fSDavid du Colombier void 1919a747e4fSDavid du Colombier closekey(Key *k) 1929a747e4fSDavid du Colombier { 1939a747e4fSDavid du Colombier if(k == nil) 1949a747e4fSDavid du Colombier return; 1959a747e4fSDavid du Colombier if(--k->ref != 0) 1969a747e4fSDavid du Colombier return; 197d9306527SDavid du Colombier if(k->proto && k->proto->closekey) 198d9306527SDavid du Colombier (*k->proto->closekey)(k); 1999a747e4fSDavid du Colombier _freeattr(k->attr); 2009a747e4fSDavid du Colombier _freeattr(k->privattr); 2019a747e4fSDavid du Colombier k->attr = (void*)~1; 2029a747e4fSDavid du Colombier k->privattr = (void*)~1; 2039a747e4fSDavid du Colombier k->proto = nil; 2049a747e4fSDavid du Colombier free(k); 2059a747e4fSDavid du Colombier } 2069a747e4fSDavid du Colombier 2079a747e4fSDavid du Colombier static uchar* 2089a747e4fSDavid du Colombier pstring(uchar *p, uchar *e, char *s) 2099a747e4fSDavid du Colombier { 2109a747e4fSDavid du Colombier uint n; 2119a747e4fSDavid du Colombier 2129a747e4fSDavid du Colombier if(p == nil) 2139a747e4fSDavid du Colombier return nil; 2149a747e4fSDavid du Colombier if(s == nil) 2159a747e4fSDavid du Colombier s = ""; 2169a747e4fSDavid du Colombier n = strlen(s); 2179a747e4fSDavid du Colombier if(p+n+BIT16SZ >= e) 2189a747e4fSDavid du Colombier return nil; 2199a747e4fSDavid du Colombier PBIT16(p, n); 2209a747e4fSDavid du Colombier p += BIT16SZ; 2219a747e4fSDavid du Colombier memmove(p, s, n); 2229a747e4fSDavid du Colombier p += n; 2239a747e4fSDavid du Colombier return p; 2249a747e4fSDavid du Colombier } 2259a747e4fSDavid du Colombier 2269a747e4fSDavid du Colombier static uchar* 2279a747e4fSDavid du Colombier pcarray(uchar *p, uchar *e, uchar *s, uint n) 2289a747e4fSDavid du Colombier { 2299a747e4fSDavid du Colombier if(p == nil) 2309a747e4fSDavid du Colombier return nil; 2319a747e4fSDavid du Colombier if(s == nil){ 2329a747e4fSDavid du Colombier if(n > 0) 2339a747e4fSDavid du Colombier sysfatal("pcarray"); 2349a747e4fSDavid du Colombier s = (uchar*)""; 2359a747e4fSDavid du Colombier } 2369a747e4fSDavid du Colombier if(p+n+BIT16SZ >= e) 2379a747e4fSDavid du Colombier return nil; 2389a747e4fSDavid du Colombier PBIT16(p, n); 2399a747e4fSDavid du Colombier p += BIT16SZ; 2409a747e4fSDavid du Colombier memmove(p, s, n); 2419a747e4fSDavid du Colombier p += n; 2429a747e4fSDavid du Colombier return p; 2439a747e4fSDavid du Colombier } 2449a747e4fSDavid du Colombier 2459a747e4fSDavid du Colombier uchar* 2469a747e4fSDavid du Colombier convAI2M(AuthInfo *ai, uchar *p, int n) 2479a747e4fSDavid du Colombier { 2489a747e4fSDavid du Colombier uchar *e = p+n; 2499a747e4fSDavid du Colombier 2509a747e4fSDavid du Colombier p = pstring(p, e, ai->cuid); 2519a747e4fSDavid du Colombier p = pstring(p, e, ai->suid); 2529a747e4fSDavid du Colombier p = pstring(p, e, ai->cap); 2539a747e4fSDavid du Colombier p = pcarray(p, e, ai->secret, ai->nsecret); 2549a747e4fSDavid du Colombier return p; 2559a747e4fSDavid du Colombier } 2569a747e4fSDavid du Colombier 2579a747e4fSDavid du Colombier int 2589a747e4fSDavid du Colombier failure(Fsstate *s, char *fmt, ...) 2599a747e4fSDavid du Colombier { 2609a747e4fSDavid du Colombier char e[ERRMAX]; 2619a747e4fSDavid du Colombier va_list arg; 2629a747e4fSDavid du Colombier 2639a747e4fSDavid du Colombier if(fmt == nil) 2649a747e4fSDavid du Colombier rerrstr(s->err, sizeof(s->err)); 2659a747e4fSDavid du Colombier else { 2669a747e4fSDavid du Colombier va_start(arg, fmt); 2679a747e4fSDavid du Colombier snprint(e, sizeof e, fmt, arg); 2689a747e4fSDavid du Colombier va_end(arg); 2699a747e4fSDavid du Colombier strecpy(s->err, s->err+sizeof(s->err), e); 2709a747e4fSDavid du Colombier errstr(e, sizeof e); 2719a747e4fSDavid du Colombier } 2729a747e4fSDavid du Colombier flog("%d: failure %s", s->seqnum, s->err); 2739a747e4fSDavid du Colombier return RpcFailure; 2749a747e4fSDavid du Colombier } 2759a747e4fSDavid du Colombier 2769a747e4fSDavid du Colombier static int 2779a747e4fSDavid du Colombier hasqueries(Attr *a) 2789a747e4fSDavid du Colombier { 2799a747e4fSDavid du Colombier for(; a; a=a->next) 2809a747e4fSDavid du Colombier if(a->type == AttrQuery) 2819a747e4fSDavid du Colombier return 1; 2829a747e4fSDavid du Colombier return 0; 2839a747e4fSDavid du Colombier } 2849a747e4fSDavid du Colombier 2859a747e4fSDavid du Colombier char *ignored[] = { 2869a747e4fSDavid du Colombier "role", 287260f7b65SDavid du Colombier "disabled", 2889a747e4fSDavid du Colombier }; 2899a747e4fSDavid du Colombier 2909a747e4fSDavid du Colombier static int 2919a747e4fSDavid du Colombier ignoreattr(char *s) 2929a747e4fSDavid du Colombier { 2939a747e4fSDavid du Colombier int i; 2949a747e4fSDavid du Colombier 2959a747e4fSDavid du Colombier for(i=0; i<nelem(ignored); i++) 2969a747e4fSDavid du Colombier if(strcmp(ignored[i], s)==0) 2979a747e4fSDavid du Colombier return 1; 2989a747e4fSDavid du Colombier return 0; 2999a747e4fSDavid du Colombier } 3009a747e4fSDavid du Colombier 301260f7b65SDavid du Colombier Keyinfo* 302260f7b65SDavid du Colombier mkkeyinfo(Keyinfo *k, Fsstate *fss, Attr *attr) 303260f7b65SDavid du Colombier { 304260f7b65SDavid du Colombier memset(k, 0, sizeof *k); 305260f7b65SDavid du Colombier k->fss = fss; 306260f7b65SDavid du Colombier k->user = fss->sysuser; 307*6b8bc682SDavid du Colombier if(attr) 308260f7b65SDavid du Colombier k->attr = attr; 309*6b8bc682SDavid du Colombier else 310*6b8bc682SDavid du Colombier k->attr = fss->attr; 311260f7b65SDavid du Colombier return k; 312260f7b65SDavid du Colombier } 313260f7b65SDavid du Colombier 3149a747e4fSDavid du Colombier int 315260f7b65SDavid du Colombier findkey(Key **ret, Keyinfo *ki, char *fmt, ...) 3169a747e4fSDavid du Colombier { 3179a747e4fSDavid du Colombier int i, s, nmatch; 318260f7b65SDavid du Colombier char buf[1024], *p, *who; 3199a747e4fSDavid du Colombier va_list arg; 320260f7b65SDavid du Colombier Attr *a, *attr0, *attr1, *attr2, *attr3, **l; 3219a747e4fSDavid du Colombier Key *k; 3229a747e4fSDavid du Colombier 3239a747e4fSDavid du Colombier *ret = nil; 3249a747e4fSDavid du Colombier 325260f7b65SDavid du Colombier who = ki->user; 326260f7b65SDavid du Colombier attr0 = ki->attr; 3279a747e4fSDavid du Colombier if(fmt){ 3289a747e4fSDavid du Colombier va_start(arg, fmt); 3299a747e4fSDavid du Colombier vseprint(buf, buf+sizeof buf, fmt, arg); 3309a747e4fSDavid du Colombier va_end(arg); 3319a747e4fSDavid du Colombier attr1 = _parseattr(buf); 3329a747e4fSDavid du Colombier }else 3339a747e4fSDavid du Colombier attr1 = nil; 3349a747e4fSDavid du Colombier 335fb7f0c93SDavid du Colombier if(who && strcmp(who, owner) == 0) 336fb7f0c93SDavid du Colombier who = nil; 337fb7f0c93SDavid du Colombier 338fb7f0c93SDavid du Colombier if(who){ 339fb7f0c93SDavid du Colombier snprint(buf, sizeof buf, "owner=%q", who); 340fb7f0c93SDavid du Colombier attr2 = _parseattr(buf); 341fb7f0c93SDavid du Colombier attr3 = _parseattr("owner=*"); 342fb7f0c93SDavid du Colombier }else 343fb7f0c93SDavid du Colombier attr2 = attr3 = nil; 344fb7f0c93SDavid du Colombier 3452ebbfa15SDavid du Colombier p = _strfindattr(attr0, "proto"); 3469a747e4fSDavid du Colombier if(p == nil) 3472ebbfa15SDavid du Colombier p = _strfindattr(attr1, "proto"); 3489a747e4fSDavid du Colombier if(p && findproto(p) == nil){ 3499a747e4fSDavid du Colombier werrstr("unknown protocol %s", p); 3509a747e4fSDavid du Colombier _freeattr(attr1); 351260f7b65SDavid du Colombier return failure(ki->fss, nil); 3529a747e4fSDavid du Colombier } 3539a747e4fSDavid du Colombier 3549a747e4fSDavid du Colombier nmatch = 0; 3559a747e4fSDavid du Colombier for(i=0; i<ring->nkey; i++){ 3569a747e4fSDavid du Colombier k = ring->key[i]; 357260f7b65SDavid du Colombier if(_strfindattr(k->attr, "disabled") && !ki->usedisabled) 358260f7b65SDavid du Colombier continue; 3599a747e4fSDavid du Colombier if(matchattr(attr0, k->attr, k->privattr) && matchattr(attr1, k->attr, k->privattr)){ 360fb7f0c93SDavid du Colombier /* check ownership */ 361fb7f0c93SDavid du Colombier if(!matchattr(attr2, k->attr, nil) && !matchattr(attr3, k->attr, nil)) 362fb7f0c93SDavid du Colombier continue; 363260f7b65SDavid du Colombier if(nmatch++ < ki->skip) 3649a747e4fSDavid du Colombier continue; 365260f7b65SDavid du Colombier if(!ki->noconf){ 366260f7b65SDavid du Colombier switch(canusekey(ki->fss, k)){ 3679a747e4fSDavid du Colombier case -1: 3689a747e4fSDavid du Colombier _freeattr(attr1); 3699a747e4fSDavid du Colombier return RpcConfirm; 3709a747e4fSDavid du Colombier case 0: 3719a747e4fSDavid du Colombier continue; 3729a747e4fSDavid du Colombier case 1: 3739a747e4fSDavid du Colombier break; 3749a747e4fSDavid du Colombier } 3759a747e4fSDavid du Colombier } 3769a747e4fSDavid du Colombier _freeattr(attr1); 3779a747e4fSDavid du Colombier k->ref++; 3789a747e4fSDavid du Colombier *ret = k; 3799a747e4fSDavid du Colombier return RpcOk; 3809a747e4fSDavid du Colombier } 3819a747e4fSDavid du Colombier } 382260f7b65SDavid du Colombier flog("%d: no key matches %A %A %A %A", ki->fss->seqnum, attr0, attr1, attr2, attr3); 3839a747e4fSDavid du Colombier werrstr("no key matches %A %A", attr0, attr1); 3849a747e4fSDavid du Colombier s = RpcFailure; 385fb7f0c93SDavid du Colombier if(askforkeys && who==nil && (hasqueries(attr0) || hasqueries(attr1))){ 3869a747e4fSDavid du Colombier if(nmatch == 0){ 3879a747e4fSDavid du Colombier attr0 = _copyattr(attr0); 3889a747e4fSDavid du Colombier for(l=&attr0; *l; l=&(*l)->next) 3899a747e4fSDavid du Colombier ; 3909a747e4fSDavid du Colombier *l = attr1; 3919a747e4fSDavid du Colombier for(l=&attr0; *l; ){ 3922ebbfa15SDavid du Colombier if(ignoreattr((*l)->name)){ 3939a747e4fSDavid du Colombier a = *l; 3949a747e4fSDavid du Colombier *l = (*l)->next; 3959a747e4fSDavid du Colombier a->next = nil; 3969a747e4fSDavid du Colombier _freeattr(a); 3979a747e4fSDavid du Colombier }else 3989a747e4fSDavid du Colombier l = &(*l)->next; 3999a747e4fSDavid du Colombier } 4009a747e4fSDavid du Colombier attr0 = sortattr(attr0); 401260f7b65SDavid du Colombier snprint(ki->fss->keyinfo, sizeof ki->fss->keyinfo, "%A", attr0); 4029a747e4fSDavid du Colombier _freeattr(attr0); 4039a747e4fSDavid du Colombier attr1 = nil; /* attr1 was linked to attr0 */ 4049a747e4fSDavid du Colombier }else 405260f7b65SDavid du Colombier ki->fss->keyinfo[0] = '\0'; 4069a747e4fSDavid du Colombier s = RpcNeedkey; 4079a747e4fSDavid du Colombier } 4089a747e4fSDavid du Colombier _freeattr(attr1); 4099a747e4fSDavid du Colombier if(s == RpcFailure) 410260f7b65SDavid du Colombier return failure(ki->fss, nil); /* loads error string */ 4119a747e4fSDavid du Colombier return s; 4129a747e4fSDavid du Colombier } 4139a747e4fSDavid du Colombier 4149a747e4fSDavid du Colombier int 4159a747e4fSDavid du Colombier findp9authkey(Key **k, Fsstate *fss) 4169a747e4fSDavid du Colombier { 4179a747e4fSDavid du Colombier char *dom; 418260f7b65SDavid du Colombier Keyinfo ki; 4199a747e4fSDavid du Colombier 4209a747e4fSDavid du Colombier /* 4219a747e4fSDavid du Colombier * We don't use fss->attr here because we don't 4229a747e4fSDavid du Colombier * care about what the user name is set to, for instance. 4239a747e4fSDavid du Colombier */ 424260f7b65SDavid du Colombier mkkeyinfo(&ki, fss, nil); 425260f7b65SDavid du Colombier ki.attr = nil; 426260f7b65SDavid du Colombier ki.user = nil; 4272ebbfa15SDavid du Colombier if(dom = _strfindattr(fss->attr, "dom")) 428260f7b65SDavid du Colombier return findkey(k, &ki, "proto=p9sk1 dom=%q role=server user?", dom); 4299a747e4fSDavid du Colombier else 430260f7b65SDavid du Colombier return findkey(k, &ki, "proto=p9sk1 role=server dom? user?"); 4319a747e4fSDavid du Colombier } 4329a747e4fSDavid du Colombier 4339a747e4fSDavid du Colombier Proto* 4349a747e4fSDavid du Colombier findproto(char *name) 4359a747e4fSDavid du Colombier { 4369a747e4fSDavid du Colombier int i; 4379a747e4fSDavid du Colombier 4389a747e4fSDavid du Colombier for(i=0; prototab[i]; i++) 4399a747e4fSDavid du Colombier if(strcmp(name, prototab[i]->name) == 0) 4409a747e4fSDavid du Colombier return prototab[i]; 4419a747e4fSDavid du Colombier return nil; 4429a747e4fSDavid du Colombier } 4439a747e4fSDavid du Colombier 4449a747e4fSDavid du Colombier char* 4459a747e4fSDavid du Colombier getnvramkey(int flag, char **secstorepw) 4469a747e4fSDavid du Colombier { 4479a747e4fSDavid du Colombier char *s; 4489a747e4fSDavid du Colombier Nvrsafe safe; 4499a747e4fSDavid du Colombier char spw[CONFIGLEN+1]; 4509a747e4fSDavid du Colombier int i; 4519a747e4fSDavid du Colombier 4529a747e4fSDavid du Colombier memset(&safe, 0, sizeof safe); 4539a747e4fSDavid du Colombier /* 4549a747e4fSDavid du Colombier * readnvram can return -1 meaning nvram wasn't written, 4559a747e4fSDavid du Colombier * but safe still holds good data. 4569a747e4fSDavid du Colombier */ 4579a747e4fSDavid du Colombier if(readnvram(&safe, flag)<0 && safe.authid[0]=='0') 4589a747e4fSDavid du Colombier return nil; 4599a747e4fSDavid du Colombier 4609a747e4fSDavid du Colombier /* 4619a747e4fSDavid du Colombier * we're using the config area to hold the secstore 4629a747e4fSDavid du Colombier * password. if there's anything there, return it. 4639a747e4fSDavid du Colombier */ 4649a747e4fSDavid du Colombier memmove(spw, safe.config, CONFIGLEN); 4659a747e4fSDavid du Colombier spw[CONFIGLEN] = 0; 4669a747e4fSDavid du Colombier if(spw[0] != 0) 4679a747e4fSDavid du Colombier *secstorepw = estrdup(spw); 4689a747e4fSDavid du Colombier 4699a747e4fSDavid du Colombier /* 4709a747e4fSDavid du Colombier * only use nvram key if it is non-zero 4719a747e4fSDavid du Colombier */ 4729a747e4fSDavid du Colombier for(i = 0; i < DESKEYLEN; i++) 4739a747e4fSDavid du Colombier if(safe.machkey[i] != 0) 4749a747e4fSDavid du Colombier break; 4759a747e4fSDavid du Colombier if(i == DESKEYLEN) 4769a747e4fSDavid du Colombier return nil; 4779a747e4fSDavid du Colombier 4789a747e4fSDavid du Colombier s = emalloc(512); 4799a747e4fSDavid du Colombier fmtinstall('H', encodefmt); 4809a747e4fSDavid du Colombier sprint(s, "key proto=p9sk1 user=%q dom=%q !hex=%.*H !password=______", 4819a747e4fSDavid du Colombier safe.authid, safe.authdom, DESKEYLEN, safe.machkey); 4829a747e4fSDavid du Colombier writehostowner(safe.authid); 4839a747e4fSDavid du Colombier 4849a747e4fSDavid du Colombier return s; 4859a747e4fSDavid du Colombier } 4869a747e4fSDavid du Colombier 4879a747e4fSDavid du Colombier int 4889a747e4fSDavid du Colombier isclient(char *role) 4899a747e4fSDavid du Colombier { 4909a747e4fSDavid du Colombier if(role == nil){ 4919a747e4fSDavid du Colombier werrstr("role not specified"); 4929a747e4fSDavid du Colombier return -1; 4939a747e4fSDavid du Colombier } 4949a747e4fSDavid du Colombier if(strcmp(role, "server") == 0) 4959a747e4fSDavid du Colombier return 0; 4969a747e4fSDavid du Colombier if(strcmp(role, "client") == 0) 4979a747e4fSDavid du Colombier return 1; 4989a747e4fSDavid du Colombier werrstr("unknown role %q", role); 4999a747e4fSDavid du Colombier return -1; 5009a747e4fSDavid du Colombier } 5019a747e4fSDavid du Colombier 5029a747e4fSDavid du Colombier static int 5039a747e4fSDavid du Colombier hasname(Attr *a0, Attr *a1, char *name) 5049a747e4fSDavid du Colombier { 5059a747e4fSDavid du Colombier return _findattr(a0, name) || _findattr(a1, name); 5069a747e4fSDavid du Colombier } 5079a747e4fSDavid du Colombier 5089a747e4fSDavid du Colombier static int 5099a747e4fSDavid du Colombier hasnameval(Attr *a0, Attr *a1, char *name, char *val) 5109a747e4fSDavid du Colombier { 5119a747e4fSDavid du Colombier Attr *a; 5129a747e4fSDavid du Colombier 5139a747e4fSDavid du Colombier for(a=_findattr(a0, name); a; a=_findattr(a->next, name)) 5142ebbfa15SDavid du Colombier if(strcmp(a->val, val) == 0) 5159a747e4fSDavid du Colombier return 1; 5169a747e4fSDavid du Colombier for(a=_findattr(a1, name); a; a=_findattr(a->next, name)) 5172ebbfa15SDavid du Colombier if(strcmp(a->val, val) == 0) 5189a747e4fSDavid du Colombier return 1; 5199a747e4fSDavid du Colombier return 0; 5209a747e4fSDavid du Colombier } 5219a747e4fSDavid du Colombier 5229a747e4fSDavid du Colombier int 5239a747e4fSDavid du Colombier matchattr(Attr *pat, Attr *a0, Attr *a1) 5249a747e4fSDavid du Colombier { 5259a747e4fSDavid du Colombier int type; 5269a747e4fSDavid du Colombier 5279a747e4fSDavid du Colombier for(; pat; pat=pat->next){ 5289a747e4fSDavid du Colombier type = pat->type; 5292ebbfa15SDavid du Colombier if(ignoreattr(pat->name)) 5309a747e4fSDavid du Colombier type = AttrDefault; 5319a747e4fSDavid du Colombier switch(type){ 5329a747e4fSDavid du Colombier case AttrQuery: /* name=something be present */ 5332ebbfa15SDavid du Colombier if(!hasname(a0, a1, pat->name)) 5349a747e4fSDavid du Colombier return 0; 5359a747e4fSDavid du Colombier break; 5369a747e4fSDavid du Colombier case AttrNameval: /* name=val must be present */ 5372ebbfa15SDavid du Colombier if(!hasnameval(a0, a1, pat->name, pat->val)) 5389a747e4fSDavid du Colombier return 0; 5399a747e4fSDavid du Colombier break; 5409a747e4fSDavid du Colombier case AttrDefault: /* name=val must be present if name=anything is present */ 5412ebbfa15SDavid du Colombier if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val)) 5429a747e4fSDavid du Colombier return 0; 5439a747e4fSDavid du Colombier break; 5449a747e4fSDavid du Colombier } 5459a747e4fSDavid du Colombier } 5469a747e4fSDavid du Colombier return 1; 5479a747e4fSDavid du Colombier } 5489a747e4fSDavid du Colombier 5499a747e4fSDavid du Colombier void 5509a747e4fSDavid du Colombier memrandom(void *p, int n) 5519a747e4fSDavid du Colombier { 5529a747e4fSDavid du Colombier uchar *cp; 5539a747e4fSDavid du Colombier 5549a747e4fSDavid du Colombier for(cp = (uchar*)p; n > 0; n--) 5559a747e4fSDavid du Colombier *cp++ = fastrand(); 5569a747e4fSDavid du Colombier } 5579a747e4fSDavid du Colombier 5589a747e4fSDavid du Colombier /* 5593ff48bf5SDavid du Colombier * keep caphash fd open since opens of it could be disabled 5603ff48bf5SDavid du Colombier */ 5613ff48bf5SDavid du Colombier static int caphashfd; 5623ff48bf5SDavid du Colombier 5633ff48bf5SDavid du Colombier void 5643ff48bf5SDavid du Colombier initcap(void) 5653ff48bf5SDavid du Colombier { 5663ff48bf5SDavid du Colombier caphashfd = open("#¤/caphash", OWRITE); 567d9306527SDavid du Colombier // if(caphashfd < 0) 568d9306527SDavid du Colombier // fprint(2, "%s: opening #¤/caphash: %r\n", argv0); 5693ff48bf5SDavid du Colombier } 5703ff48bf5SDavid du Colombier 5713ff48bf5SDavid du Colombier /* 5729a747e4fSDavid du Colombier * create a change uid capability 5739a747e4fSDavid du Colombier */ 5749a747e4fSDavid du Colombier char* 5753ff48bf5SDavid du Colombier mkcap(char *from, char *to) 5769a747e4fSDavid du Colombier { 5779a747e4fSDavid du Colombier uchar rand[20]; 5789a747e4fSDavid du Colombier char *cap; 5799a747e4fSDavid du Colombier char *key; 5803ff48bf5SDavid du Colombier int nfrom, nto; 5819a747e4fSDavid du Colombier uchar hash[SHA1dlen]; 5829a747e4fSDavid du Colombier 5833ff48bf5SDavid du Colombier if(caphashfd < 0) 5849a747e4fSDavid du Colombier return nil; 5859a747e4fSDavid du Colombier 5869a747e4fSDavid du Colombier /* create the capability */ 5873ff48bf5SDavid du Colombier nto = strlen(to); 5883ff48bf5SDavid du Colombier nfrom = strlen(from); 5893ff48bf5SDavid du Colombier cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1); 5903ff48bf5SDavid du Colombier sprint(cap, "%s@%s", from, to); 5919a747e4fSDavid du Colombier memrandom(rand, sizeof(rand)); 5923ff48bf5SDavid du Colombier key = cap+nfrom+1+nto+1; 5939a747e4fSDavid du Colombier enc64(key, sizeof(rand)*3, rand, sizeof(rand)); 5949a747e4fSDavid du Colombier 5959a747e4fSDavid du Colombier /* hash the capability */ 5963ff48bf5SDavid du Colombier hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil); 5979a747e4fSDavid du Colombier 5989a747e4fSDavid du Colombier /* give the kernel the hash */ 5993ff48bf5SDavid du Colombier key[-1] = '@'; 6003ff48bf5SDavid du Colombier if(write(caphashfd, hash, SHA1dlen) < 0){ 6019a747e4fSDavid du Colombier free(cap); 6029a747e4fSDavid du Colombier return nil; 6039a747e4fSDavid du Colombier } 6049a747e4fSDavid du Colombier 6059a747e4fSDavid du Colombier return cap; 6069a747e4fSDavid du Colombier } 6079a747e4fSDavid du Colombier 6089a747e4fSDavid du Colombier int 6099a747e4fSDavid du Colombier phaseerror(Fsstate *s, char *op) 6109a747e4fSDavid du Colombier { 6119a747e4fSDavid du Colombier char tmp[32]; 6129a747e4fSDavid du Colombier 6139a747e4fSDavid du Colombier werrstr("protocol phase error: %s in state %s", op, phasename(s, s->phase, tmp)); 6149a747e4fSDavid du Colombier return RpcPhase; 6159a747e4fSDavid du Colombier } 6169a747e4fSDavid du Colombier 6179a747e4fSDavid du Colombier char* 6189a747e4fSDavid du Colombier phasename(Fsstate *fss, int phase, char *tmp) 6199a747e4fSDavid du Colombier { 6209a747e4fSDavid du Colombier char *name; 6219a747e4fSDavid du Colombier 6229a747e4fSDavid du Colombier if(fss->phase == Broken) 6239a747e4fSDavid du Colombier name = "Broken"; 6249a747e4fSDavid du Colombier else if(phase == Established) 6259a747e4fSDavid du Colombier name = "Established"; 6269a747e4fSDavid du Colombier else if(phase == Notstarted) 6279a747e4fSDavid du Colombier name = "Notstarted"; 6289a747e4fSDavid du Colombier else if(phase < 0 || phase >= fss->maxphase 6299a747e4fSDavid du Colombier || (name = fss->phasename[phase]) == nil){ 6309a747e4fSDavid du Colombier sprint(tmp, "%d", phase); 6319a747e4fSDavid du Colombier name = tmp; 6329a747e4fSDavid du Colombier } 6339a747e4fSDavid du Colombier return name; 6349a747e4fSDavid du Colombier } 6359a747e4fSDavid du Colombier 6369a747e4fSDavid du Colombier static int 6379a747e4fSDavid du Colombier outin(char *prompt, char *def, int len) 6389a747e4fSDavid du Colombier { 6392ebbfa15SDavid du Colombier char *s; 6409a747e4fSDavid du Colombier 6419a747e4fSDavid du Colombier s = readcons(prompt, def, 0); 6429a747e4fSDavid du Colombier if(s == nil) 6439a747e4fSDavid du Colombier return -1; 6442ebbfa15SDavid du Colombier if(s == nil) 6452ebbfa15SDavid du Colombier sysfatal("s==nil???"); 6462ebbfa15SDavid du Colombier strncpy(def, s, len); 6479a747e4fSDavid du Colombier def[len-1] = 0; 6482ebbfa15SDavid du Colombier free(s); 6499a747e4fSDavid du Colombier return strlen(def); 6509a747e4fSDavid du Colombier } 6519a747e4fSDavid du Colombier 6529a747e4fSDavid du Colombier /* 6539a747e4fSDavid du Colombier * get host owner and set it 6549a747e4fSDavid du Colombier */ 6559a747e4fSDavid du Colombier void 6569a747e4fSDavid du Colombier promptforhostowner(void) 6579a747e4fSDavid du Colombier { 6589a747e4fSDavid du Colombier char owner[64], *p; 6599a747e4fSDavid du Colombier 6609a747e4fSDavid du Colombier /* hack for bitsy; can't prompt during boot */ 6619a747e4fSDavid du Colombier if(p = getenv("user")){ 6629a747e4fSDavid du Colombier writehostowner(p); 663d9306527SDavid du Colombier free(p); 6649a747e4fSDavid du Colombier return; 6659a747e4fSDavid du Colombier } 666d9306527SDavid du Colombier free(p); 6679a747e4fSDavid du Colombier 6689a747e4fSDavid du Colombier strcpy(owner, "none"); 6699a747e4fSDavid du Colombier do{ 6709a747e4fSDavid du Colombier outin("user", owner, sizeof(owner)); 6719a747e4fSDavid du Colombier } while(*owner == 0); 6729a747e4fSDavid du Colombier writehostowner(owner); 6739a747e4fSDavid du Colombier } 6749a747e4fSDavid du Colombier 6752ebbfa15SDavid du Colombier char* 6762ebbfa15SDavid du Colombier estrappend(char *s, char *fmt, ...) 6772ebbfa15SDavid du Colombier { 6782ebbfa15SDavid du Colombier char *t; 6792ebbfa15SDavid du Colombier va_list arg; 6802ebbfa15SDavid du Colombier 6812ebbfa15SDavid du Colombier va_start(arg, fmt); 6822ebbfa15SDavid du Colombier t = vsmprint(fmt, arg); 6832ebbfa15SDavid du Colombier if(t == nil) 6842ebbfa15SDavid du Colombier sysfatal("out of memory"); 6852ebbfa15SDavid du Colombier va_end(arg); 6862ebbfa15SDavid du Colombier s = erealloc(s, strlen(s)+strlen(t)+1); 6872ebbfa15SDavid du Colombier strcat(s, t); 6882ebbfa15SDavid du Colombier free(t); 6892ebbfa15SDavid du Colombier return s; 6902ebbfa15SDavid du Colombier } 6912ebbfa15SDavid du Colombier 6922ebbfa15SDavid du Colombier 6939a747e4fSDavid du Colombier /* 6949a747e4fSDavid du Colombier * prompt for a string with a possible default response 6959a747e4fSDavid du Colombier */ 6962ebbfa15SDavid du Colombier char* 6979a747e4fSDavid du Colombier readcons(char *prompt, char *def, int raw) 6989a747e4fSDavid du Colombier { 6999a747e4fSDavid du Colombier int fdin, fdout, ctl, n; 7009a747e4fSDavid du Colombier char line[10]; 7012ebbfa15SDavid du Colombier char *s; 7029a747e4fSDavid du Colombier 7039a747e4fSDavid du Colombier fdin = open("/dev/cons", OREAD); 7049a747e4fSDavid du Colombier if(fdin < 0) 7059a747e4fSDavid du Colombier fdin = 0; 7069a747e4fSDavid du Colombier fdout = open("/dev/cons", OWRITE); 7079a747e4fSDavid du Colombier if(fdout < 0) 7089a747e4fSDavid du Colombier fdout = 1; 7099a747e4fSDavid du Colombier if(def != nil) 7109a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 7119a747e4fSDavid du Colombier else 7129a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 7139a747e4fSDavid du Colombier if(raw){ 7149a747e4fSDavid du Colombier ctl = open("/dev/consctl", OWRITE); 7159a747e4fSDavid du Colombier if(ctl >= 0) 7169a747e4fSDavid du Colombier write(ctl, "rawon", 5); 7179a747e4fSDavid du Colombier } else 7189a747e4fSDavid du Colombier ctl = -1; 7192ebbfa15SDavid du Colombier s = estrdup(""); 7209a747e4fSDavid du Colombier for(;;){ 7219a747e4fSDavid du Colombier n = read(fdin, line, 1); 7229a747e4fSDavid du Colombier if(n == 0){ 7239a747e4fSDavid du Colombier Error: 7249a747e4fSDavid du Colombier close(fdin); 7259a747e4fSDavid du Colombier close(fdout); 7269a747e4fSDavid du Colombier if(ctl >= 0) 7279a747e4fSDavid du Colombier close(ctl); 7282ebbfa15SDavid du Colombier free(s); 7299a747e4fSDavid du Colombier return nil; 7309a747e4fSDavid du Colombier } 7319a747e4fSDavid du Colombier if(n < 0) 7329a747e4fSDavid du Colombier goto Error; 7339a747e4fSDavid du Colombier if(line[0] == 0x7f) 7349a747e4fSDavid du Colombier goto Error; 7359a747e4fSDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){ 7369a747e4fSDavid du Colombier if(raw){ 7379a747e4fSDavid du Colombier write(ctl, "rawoff", 6); 7389a747e4fSDavid du Colombier write(fdout, "\n", 1); 7399a747e4fSDavid du Colombier } 7409a747e4fSDavid du Colombier close(ctl); 7419a747e4fSDavid du Colombier close(fdin); 7429a747e4fSDavid du Colombier close(fdout); 7432ebbfa15SDavid du Colombier if(*s == 0 && def != nil) 7442ebbfa15SDavid du Colombier s = estrappend(s, "%s", def); 7459a747e4fSDavid du Colombier return s; 7469a747e4fSDavid du Colombier } 7479a747e4fSDavid du Colombier if(line[0] == '\b'){ 7482ebbfa15SDavid du Colombier if(strlen(s) > 0) 7492ebbfa15SDavid du Colombier s[strlen(s)-1] = 0; 7509a747e4fSDavid du Colombier } else if(line[0] == 0x15) { /* ^U: line kill */ 7512ebbfa15SDavid du Colombier if(def != nil) 7522ebbfa15SDavid du Colombier fprint(fdout, "\n%s[%s]: ", prompt, def); 7532ebbfa15SDavid du Colombier else 7542ebbfa15SDavid du Colombier fprint(fdout, "\n%s: ", prompt); 7552ebbfa15SDavid du Colombier 7562ebbfa15SDavid du Colombier s[0] = 0; 7579a747e4fSDavid du Colombier } else { 7582ebbfa15SDavid du Colombier s = estrappend(s, "%c", line[0]); 7599a747e4fSDavid du Colombier } 7609a747e4fSDavid du Colombier } 7612ebbfa15SDavid du Colombier return nil; /* not reached */ 7629a747e4fSDavid du Colombier } 7639a747e4fSDavid du Colombier 7649a747e4fSDavid du Colombier /* 7659a747e4fSDavid du Colombier * Insert a key into the keyring. 7669a747e4fSDavid du Colombier * If the public attributes are identical to some other key, replace that one. 7679a747e4fSDavid du Colombier */ 7689a747e4fSDavid du Colombier int 76970b8e010SDavid du Colombier replacekey(Key *kn, int before) 7709a747e4fSDavid du Colombier { 7719a747e4fSDavid du Colombier int i; 7729a747e4fSDavid du Colombier Key *k; 7739a747e4fSDavid du Colombier 7749a747e4fSDavid du Colombier for(i=0; i<ring->nkey; i++){ 7759a747e4fSDavid du Colombier k = ring->key[i]; 7769a747e4fSDavid du Colombier if(matchattr(kn->attr, k->attr, nil) && matchattr(k->attr, kn->attr, nil)){ 7779a747e4fSDavid du Colombier closekey(k); 7789a747e4fSDavid du Colombier kn->ref++; 7799a747e4fSDavid du Colombier ring->key[i] = kn; 7809a747e4fSDavid du Colombier return 0; 7819a747e4fSDavid du Colombier } 7829a747e4fSDavid du Colombier } 7839a747e4fSDavid du Colombier if(ring->nkey%16 == 0) 7849a747e4fSDavid du Colombier ring->key = erealloc(ring->key, (ring->nkey+16)*sizeof(ring->key[0])); 7859a747e4fSDavid du Colombier kn->ref++; 78670b8e010SDavid du Colombier if(before){ 78770b8e010SDavid du Colombier memmove(ring->key+1, ring->key, ring->nkey*sizeof ring->key[0]); 78870b8e010SDavid du Colombier ring->key[0] = kn; 78970b8e010SDavid du Colombier ring->nkey++; 79070b8e010SDavid du Colombier }else 7919a747e4fSDavid du Colombier ring->key[ring->nkey++] = kn; 7929a747e4fSDavid du Colombier return 0; 7939a747e4fSDavid du Colombier } 7949a747e4fSDavid du Colombier 7959a747e4fSDavid du Colombier char* 7969a747e4fSDavid du Colombier safecpy(char *to, char *from, int n) 7979a747e4fSDavid du Colombier { 7989a747e4fSDavid du Colombier memset(to, 0, n); 7999a747e4fSDavid du Colombier if(n == 1) 8009a747e4fSDavid du Colombier return to; 8019a747e4fSDavid du Colombier if(from==nil) 8029a747e4fSDavid du Colombier sysfatal("safecpy called with from==nil, pc=%lux\n", 8039a747e4fSDavid du Colombier getcallerpc(&to)); 8049a747e4fSDavid du Colombier strncpy(to, from, n-1); 8059a747e4fSDavid du Colombier return to; 8069a747e4fSDavid du Colombier } 8079a747e4fSDavid du Colombier 8089a747e4fSDavid du Colombier Attr* 8099a747e4fSDavid du Colombier setattr(Attr *a, char *fmt, ...) 8109a747e4fSDavid du Colombier { 8119a747e4fSDavid du Colombier char buf[1024]; 8129a747e4fSDavid du Colombier va_list arg; 8139a747e4fSDavid du Colombier Attr *b; 8149a747e4fSDavid du Colombier 8159a747e4fSDavid du Colombier va_start(arg, fmt); 8169a747e4fSDavid du Colombier vseprint(buf, buf+sizeof buf, fmt, arg); 8179a747e4fSDavid du Colombier va_end(arg); 8189a747e4fSDavid du Colombier b = _parseattr(buf); 8199a747e4fSDavid du Colombier a = setattrs(a, b); 8209a747e4fSDavid du Colombier setmalloctag(a, getcallerpc(&a)); 8219a747e4fSDavid du Colombier _freeattr(b); 8229a747e4fSDavid du Colombier return a; 8239a747e4fSDavid du Colombier } 8249a747e4fSDavid du Colombier 8259a747e4fSDavid du Colombier /* 8269a747e4fSDavid du Colombier * add attributes in list b to list a. If any attributes are in 8279a747e4fSDavid du Colombier * both lists, replace those in a by those in b. 8289a747e4fSDavid du Colombier */ 8299a747e4fSDavid du Colombier Attr* 8309a747e4fSDavid du Colombier setattrs(Attr *a, Attr *b) 8319a747e4fSDavid du Colombier { 8329a747e4fSDavid du Colombier int found; 8339a747e4fSDavid du Colombier Attr **l, *freea; 8349a747e4fSDavid du Colombier 8359a747e4fSDavid du Colombier for(; b; b=b->next){ 8369a747e4fSDavid du Colombier found = 0; 8379a747e4fSDavid du Colombier for(l=&a; *l; ){ 8382ebbfa15SDavid du Colombier if(strcmp(b->name, (*l)->name) == 0){ 8399a747e4fSDavid du Colombier switch(b->type){ 8409a747e4fSDavid du Colombier case AttrNameval: 8419a747e4fSDavid du Colombier if(!found){ 8429a747e4fSDavid du Colombier found = 1; 8432ebbfa15SDavid du Colombier free((*l)->val); 8442ebbfa15SDavid du Colombier (*l)->val = estrdup(b->val); 8459a747e4fSDavid du Colombier (*l)->type = AttrNameval; 8469a747e4fSDavid du Colombier l = &(*l)->next; 8479a747e4fSDavid du Colombier }else{ 8489a747e4fSDavid du Colombier freea = *l; 8499a747e4fSDavid du Colombier *l = (*l)->next; 8509a747e4fSDavid du Colombier freea->next = nil; 8519a747e4fSDavid du Colombier _freeattr(freea); 8529a747e4fSDavid du Colombier } 8539a747e4fSDavid du Colombier break; 8549a747e4fSDavid du Colombier case AttrQuery: 8559a747e4fSDavid du Colombier found++; 8569a747e4fSDavid du Colombier break; 8579a747e4fSDavid du Colombier } 8589a747e4fSDavid du Colombier }else 8599a747e4fSDavid du Colombier l = &(*l)->next; 8609a747e4fSDavid du Colombier } 8619a747e4fSDavid du Colombier if(found == 0){ 8622ebbfa15SDavid du Colombier *l = _mkattr(b->type, b->name, b->val, nil); 8639a747e4fSDavid du Colombier setmalloctag(*l, getcallerpc(&a)); 8649a747e4fSDavid du Colombier } 8659a747e4fSDavid du Colombier } 8669a747e4fSDavid du Colombier return a; 8679a747e4fSDavid du Colombier } 8689a747e4fSDavid du Colombier 8699a747e4fSDavid du Colombier void 8709a747e4fSDavid du Colombier setmalloctaghere(void *v) 8719a747e4fSDavid du Colombier { 8729a747e4fSDavid du Colombier setmalloctag(v, getcallerpc(&v)); 8739a747e4fSDavid du Colombier } 8749a747e4fSDavid du Colombier 8759a747e4fSDavid du Colombier Attr* 8769a747e4fSDavid du Colombier sortattr(Attr *a) 8779a747e4fSDavid du Colombier { 8789a747e4fSDavid du Colombier int i; 8799a747e4fSDavid du Colombier Attr *anext, *a0, *a1, **l; 8809a747e4fSDavid du Colombier 8819a747e4fSDavid du Colombier if(a == nil || a->next == nil) 8829a747e4fSDavid du Colombier return a; 8839a747e4fSDavid du Colombier 8849a747e4fSDavid du Colombier /* cut list in halves */ 8859a747e4fSDavid du Colombier a0 = nil; 8869a747e4fSDavid du Colombier a1 = nil; 8879a747e4fSDavid du Colombier i = 0; 8889a747e4fSDavid du Colombier for(; a; a=anext){ 8899a747e4fSDavid du Colombier anext = a->next; 8909a747e4fSDavid du Colombier if(i++%2){ 8919a747e4fSDavid du Colombier a->next = a0; 8929a747e4fSDavid du Colombier a0 = a; 8939a747e4fSDavid du Colombier }else{ 8949a747e4fSDavid du Colombier a->next = a1; 8959a747e4fSDavid du Colombier a1 = a; 8969a747e4fSDavid du Colombier } 8979a747e4fSDavid du Colombier } 8989a747e4fSDavid du Colombier 8999a747e4fSDavid du Colombier /* sort */ 9009a747e4fSDavid du Colombier a0 = sortattr(a0); 9019a747e4fSDavid du Colombier a1 = sortattr(a1); 9029a747e4fSDavid du Colombier 9039a747e4fSDavid du Colombier /* merge */ 9049a747e4fSDavid du Colombier l = &a; 9059a747e4fSDavid du Colombier while(a0 || a1){ 9069a747e4fSDavid du Colombier if(a1==nil){ 9079a747e4fSDavid du Colombier anext = a0; 9089a747e4fSDavid du Colombier a0 = a0->next; 9099a747e4fSDavid du Colombier }else if(a0==nil){ 9109a747e4fSDavid du Colombier anext = a1; 9119a747e4fSDavid du Colombier a1 = a1->next; 9122ebbfa15SDavid du Colombier }else if(strcmp(a0->name, a1->name) < 0){ 9139a747e4fSDavid du Colombier anext = a0; 9149a747e4fSDavid du Colombier a0 = a0->next; 9159a747e4fSDavid du Colombier }else{ 9169a747e4fSDavid du Colombier anext = a1; 9179a747e4fSDavid du Colombier a1 = a1->next; 9189a747e4fSDavid du Colombier } 9199a747e4fSDavid du Colombier *l = anext; 9209a747e4fSDavid du Colombier l = &(*l)->next; 9219a747e4fSDavid du Colombier } 9229a747e4fSDavid du Colombier *l = nil; 9239a747e4fSDavid du Colombier return a; 9249a747e4fSDavid du Colombier } 9259a747e4fSDavid du Colombier 9269a747e4fSDavid du Colombier int 9279a747e4fSDavid du Colombier toosmall(Fsstate *fss, uint n) 9289a747e4fSDavid du Colombier { 9299a747e4fSDavid du Colombier fss->rpc.nwant = n; 9309a747e4fSDavid du Colombier return RpcToosmall; 9319a747e4fSDavid du Colombier } 9329a747e4fSDavid du Colombier 9339a747e4fSDavid du Colombier void 9349a747e4fSDavid du Colombier writehostowner(char *owner) 9359a747e4fSDavid du Colombier { 9369a747e4fSDavid du Colombier int fd; 9379a747e4fSDavid du Colombier char *s; 9389a747e4fSDavid du Colombier 9399a747e4fSDavid du Colombier if((s = strchr(owner,'@')) != nil){ 9409a747e4fSDavid du Colombier *s++ = 0; 9419a747e4fSDavid du Colombier strncpy(secstore, s, (sizeof secstore)-1); 9429a747e4fSDavid du Colombier } 9439a747e4fSDavid du Colombier fd = open("#c/hostowner", OWRITE); 9449a747e4fSDavid du Colombier if(fd >= 0){ 9459a747e4fSDavid du Colombier if(fprint(fd, "%s", owner) < 0) 9469a747e4fSDavid du Colombier fprint(2, "setting #c/hostowner to %q: %r\n", owner); 9479a747e4fSDavid du Colombier close(fd); 9489a747e4fSDavid du Colombier } 9499a747e4fSDavid du Colombier } 9509a747e4fSDavid du Colombier 9515d459b5aSDavid du Colombier int 9525d459b5aSDavid du Colombier attrnamefmt(Fmt *fmt) 9535d459b5aSDavid du Colombier { 9545d459b5aSDavid du Colombier char *b, buf[1024], *ebuf; 9555d459b5aSDavid du Colombier Attr *a; 9565d459b5aSDavid du Colombier 9575d459b5aSDavid du Colombier ebuf = buf+sizeof buf; 9585d459b5aSDavid du Colombier b = buf; 9595d459b5aSDavid du Colombier strcpy(buf, " "); 9605d459b5aSDavid du Colombier for(a=va_arg(fmt->args, Attr*); a; a=a->next){ 9615d459b5aSDavid du Colombier if(a->name == nil) 9625d459b5aSDavid du Colombier continue; 9632ebbfa15SDavid du Colombier b = seprint(b, ebuf, " %q?", a->name); 9645d459b5aSDavid du Colombier } 9655d459b5aSDavid du Colombier return fmtstrcpy(fmt, buf+1); 9665d459b5aSDavid du Colombier } 967260f7b65SDavid du Colombier 968260f7b65SDavid du Colombier void 969260f7b65SDavid du Colombier disablekey(Key *k) 970260f7b65SDavid du Colombier { 971260f7b65SDavid du Colombier Attr *a; 972260f7b65SDavid du Colombier 973260f7b65SDavid du Colombier for(a=k->attr; a; a=a->next){ 974260f7b65SDavid du Colombier if(a->type==AttrNameval && strcmp(a->name, "disabled") == 0) 975260f7b65SDavid du Colombier return; 976260f7b65SDavid du Colombier if(a->next == nil) 977260f7b65SDavid du Colombier break; 978260f7b65SDavid du Colombier } 979260f7b65SDavid du Colombier if(a) 980260f7b65SDavid du Colombier a->next = _mkattr(AttrNameval, "disabled", "by.factotum", nil); 981260f7b65SDavid du Colombier else 982260f7b65SDavid du Colombier k->attr = _mkattr(AttrNameval, "disabled", "by.factotum", nil); /* not reached: always a proto attribute */ 983260f7b65SDavid du Colombier } 984