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 11*d9306527SDavid 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) 1039a747e4fSDavid du Colombier if(a->type != AttrQuery && s_to_c(a->name)[0] != '!') 1049a747e4fSDavid du Colombier fprint(fd, " %q=%q", s_to_c(a->name), s_to_c(a->val)); 1059a747e4fSDavid du Colombier fprint(fd, "\n"); 1069a747e4fSDavid du Colombier 1079a747e4fSDavid du Colombier for(a=attr; a; a=a->next){ 1089a747e4fSDavid du Colombier v = s_to_c(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){ 1209a747e4fSDavid du Colombier v = s_to_c(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 1739a747e4fSDavid du Colombier if(_str_findattr(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; 197*d9306527SDavid du Colombier if(k->proto && k->proto->closekey) 198*d9306527SDavid 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", 2879a747e4fSDavid du Colombier }; 2889a747e4fSDavid du Colombier 2899a747e4fSDavid du Colombier static int 2909a747e4fSDavid du Colombier ignoreattr(char *s) 2919a747e4fSDavid du Colombier { 2929a747e4fSDavid du Colombier int i; 2939a747e4fSDavid du Colombier 2949a747e4fSDavid du Colombier for(i=0; i<nelem(ignored); i++) 2959a747e4fSDavid du Colombier if(strcmp(ignored[i], s)==0) 2969a747e4fSDavid du Colombier return 1; 2979a747e4fSDavid du Colombier return 0; 2989a747e4fSDavid du Colombier } 2999a747e4fSDavid du Colombier 3009a747e4fSDavid du Colombier int 3019a747e4fSDavid du Colombier findkey(Key **ret, Fsstate *fss, int who, int skip, Attr *attr0, char *fmt, ...) 3029a747e4fSDavid du Colombier { 3039a747e4fSDavid du Colombier int i, s, nmatch; 3049a747e4fSDavid du Colombier char buf[1024], *p; 3059a747e4fSDavid du Colombier va_list arg; 3069a747e4fSDavid du Colombier Attr *a, *attr1, **l; 3079a747e4fSDavid du Colombier Key *k; 3089a747e4fSDavid du Colombier 3099a747e4fSDavid du Colombier *ret = nil; 3109a747e4fSDavid du Colombier switch(who&Kwho){ 3119a747e4fSDavid du Colombier default: 3129a747e4fSDavid du Colombier werrstr("bad who %d", who); 3139a747e4fSDavid du Colombier failure(fss, nil); 3149a747e4fSDavid du Colombier return failure(fss, nil); 3159a747e4fSDavid du Colombier case Kowner: 3169a747e4fSDavid du Colombier break; 3179a747e4fSDavid du Colombier case Kuser: 318*d9306527SDavid du Colombier if(strcmp(fss->sysuser, owner) != 0 319*d9306527SDavid du Colombier && strcmp(fss->sysuser, invoker) != 0){ 3209a747e4fSDavid du Colombier werrstr("%q can't use %q's keys", fss->sysuser, owner); 3219a747e4fSDavid du Colombier return failure(fss, nil); 3229a747e4fSDavid du Colombier } 3239a747e4fSDavid du Colombier break; 3249a747e4fSDavid du Colombier } 3259a747e4fSDavid du Colombier 3269a747e4fSDavid du Colombier if(fmt){ 3279a747e4fSDavid du Colombier va_start(arg, fmt); 3289a747e4fSDavid du Colombier vseprint(buf, buf+sizeof buf, fmt, arg); 3299a747e4fSDavid du Colombier va_end(arg); 3309a747e4fSDavid du Colombier attr1 = _parseattr(buf); 3319a747e4fSDavid du Colombier }else 3329a747e4fSDavid du Colombier attr1 = nil; 3339a747e4fSDavid du Colombier 3349a747e4fSDavid du Colombier p = _str_findattr(attr0, "proto"); 3359a747e4fSDavid du Colombier if(p == nil) 3369a747e4fSDavid du Colombier p = _str_findattr(attr1, "proto"); 3379a747e4fSDavid du Colombier if(p && findproto(p) == nil){ 3389a747e4fSDavid du Colombier werrstr("unknown protocol %s", p); 3399a747e4fSDavid du Colombier _freeattr(attr1); 3409a747e4fSDavid du Colombier return failure(fss, nil); 3419a747e4fSDavid du Colombier } 3429a747e4fSDavid du Colombier 3439a747e4fSDavid du Colombier nmatch = 0; 3449a747e4fSDavid du Colombier for(i=0; i<ring->nkey; i++){ 3459a747e4fSDavid du Colombier k = ring->key[i]; 3469a747e4fSDavid du Colombier if(matchattr(attr0, k->attr, k->privattr) && matchattr(attr1, k->attr, k->privattr)){ 3479a747e4fSDavid du Colombier if(nmatch++ < skip) 3489a747e4fSDavid du Colombier continue; 3499a747e4fSDavid du Colombier if(!(who&Knoconf)){ 3509a747e4fSDavid du Colombier switch(canusekey(fss, k)){ 3519a747e4fSDavid du Colombier case -1: 3529a747e4fSDavid du Colombier _freeattr(attr1); 3539a747e4fSDavid du Colombier return RpcConfirm; 3549a747e4fSDavid du Colombier case 0: 3559a747e4fSDavid du Colombier continue; 3569a747e4fSDavid du Colombier case 1: 3579a747e4fSDavid du Colombier break; 3589a747e4fSDavid du Colombier } 3599a747e4fSDavid du Colombier } 3609a747e4fSDavid du Colombier _freeattr(attr1); 3619a747e4fSDavid du Colombier k->ref++; 3629a747e4fSDavid du Colombier *ret = k; 3639a747e4fSDavid du Colombier return RpcOk; 3649a747e4fSDavid du Colombier } 3659a747e4fSDavid du Colombier } 3669a747e4fSDavid du Colombier flog("%d: no key matches %A %A", fss->seqnum, attr0, attr1); 3679a747e4fSDavid du Colombier werrstr("no key matches %A %A", attr0, attr1); 3689a747e4fSDavid du Colombier s = RpcFailure; 3699a747e4fSDavid du Colombier if(askforkeys && (hasqueries(attr0) || hasqueries(attr1))){ 3709a747e4fSDavid du Colombier if(nmatch == 0){ 3719a747e4fSDavid du Colombier attr0 = _copyattr(attr0); 3729a747e4fSDavid du Colombier for(l=&attr0; *l; l=&(*l)->next) 3739a747e4fSDavid du Colombier ; 3749a747e4fSDavid du Colombier *l = attr1; 3759a747e4fSDavid du Colombier for(l=&attr0; *l; ){ 3769a747e4fSDavid du Colombier if(ignoreattr(s_to_c((*l)->name))){ 3779a747e4fSDavid du Colombier a = *l; 3789a747e4fSDavid du Colombier *l = (*l)->next; 3799a747e4fSDavid du Colombier a->next = nil; 3809a747e4fSDavid du Colombier _freeattr(a); 3819a747e4fSDavid du Colombier }else 3829a747e4fSDavid du Colombier l = &(*l)->next; 3839a747e4fSDavid du Colombier } 3849a747e4fSDavid du Colombier attr0 = sortattr(attr0); 3859a747e4fSDavid du Colombier snprint(fss->keyinfo, sizeof fss->keyinfo, "%A", attr0); 3869a747e4fSDavid du Colombier _freeattr(attr0); 3879a747e4fSDavid du Colombier attr1 = nil; /* attr1 was linked to attr0 */ 3889a747e4fSDavid du Colombier }else 3899a747e4fSDavid du Colombier fss->keyinfo[0] = '\0'; 3909a747e4fSDavid du Colombier s = RpcNeedkey; 3919a747e4fSDavid du Colombier } 3929a747e4fSDavid du Colombier _freeattr(attr1); 3939a747e4fSDavid du Colombier if(s == RpcFailure) 3949a747e4fSDavid du Colombier return failure(fss, nil); /* loads error string */ 3959a747e4fSDavid du Colombier return s; 3969a747e4fSDavid du Colombier } 3979a747e4fSDavid du Colombier 3989a747e4fSDavid du Colombier int 3999a747e4fSDavid du Colombier findp9authkey(Key **k, Fsstate *fss) 4009a747e4fSDavid du Colombier { 4019a747e4fSDavid du Colombier char *dom; 4029a747e4fSDavid du Colombier 4039a747e4fSDavid du Colombier /* 4049a747e4fSDavid du Colombier * We don't use fss->attr here because we don't 4059a747e4fSDavid du Colombier * care about what the user name is set to, for instance. 4069a747e4fSDavid du Colombier */ 4079a747e4fSDavid du Colombier if(dom = _str_findattr(fss->attr, "dom")) 4089a747e4fSDavid du Colombier return findkey(k, fss, Kowner, 0, nil, "proto=p9sk1 dom=%q role=server user?", dom); 4099a747e4fSDavid du Colombier else 4109a747e4fSDavid du Colombier return findkey(k, fss, Kowner, 0, nil, "proto=p9sk1 role=server dom? user?"); 4119a747e4fSDavid du Colombier } 4129a747e4fSDavid du Colombier 4139a747e4fSDavid du Colombier Proto* 4149a747e4fSDavid du Colombier findproto(char *name) 4159a747e4fSDavid du Colombier { 4169a747e4fSDavid du Colombier int i; 4179a747e4fSDavid du Colombier 4189a747e4fSDavid du Colombier for(i=0; prototab[i]; i++) 4199a747e4fSDavid du Colombier if(strcmp(name, prototab[i]->name) == 0) 4209a747e4fSDavid du Colombier return prototab[i]; 4219a747e4fSDavid du Colombier return nil; 4229a747e4fSDavid du Colombier } 4239a747e4fSDavid du Colombier 4249a747e4fSDavid du Colombier char* 4259a747e4fSDavid du Colombier getnvramkey(int flag, char **secstorepw) 4269a747e4fSDavid du Colombier { 4279a747e4fSDavid du Colombier char *s; 4289a747e4fSDavid du Colombier Nvrsafe safe; 4299a747e4fSDavid du Colombier char spw[CONFIGLEN+1]; 4309a747e4fSDavid du Colombier int i; 4319a747e4fSDavid du Colombier 4329a747e4fSDavid du Colombier memset(&safe, 0, sizeof safe); 4339a747e4fSDavid du Colombier /* 4349a747e4fSDavid du Colombier * readnvram can return -1 meaning nvram wasn't written, 4359a747e4fSDavid du Colombier * but safe still holds good data. 4369a747e4fSDavid du Colombier */ 4379a747e4fSDavid du Colombier if(readnvram(&safe, flag)<0 && safe.authid[0]=='0') 4389a747e4fSDavid du Colombier return nil; 4399a747e4fSDavid du Colombier 4409a747e4fSDavid du Colombier /* 4419a747e4fSDavid du Colombier * we're using the config area to hold the secstore 4429a747e4fSDavid du Colombier * password. if there's anything there, return it. 4439a747e4fSDavid du Colombier */ 4449a747e4fSDavid du Colombier memmove(spw, safe.config, CONFIGLEN); 4459a747e4fSDavid du Colombier spw[CONFIGLEN] = 0; 4469a747e4fSDavid du Colombier if(spw[0] != 0) 4479a747e4fSDavid du Colombier *secstorepw = estrdup(spw); 4489a747e4fSDavid du Colombier 4499a747e4fSDavid du Colombier /* 4509a747e4fSDavid du Colombier * only use nvram key if it is non-zero 4519a747e4fSDavid du Colombier */ 4529a747e4fSDavid du Colombier for(i = 0; i < DESKEYLEN; i++) 4539a747e4fSDavid du Colombier if(safe.machkey[i] != 0) 4549a747e4fSDavid du Colombier break; 4559a747e4fSDavid du Colombier if(i == DESKEYLEN) 4569a747e4fSDavid du Colombier return nil; 4579a747e4fSDavid du Colombier 4589a747e4fSDavid du Colombier s = emalloc(512); 4599a747e4fSDavid du Colombier fmtinstall('H', encodefmt); 4609a747e4fSDavid du Colombier sprint(s, "key proto=p9sk1 user=%q dom=%q !hex=%.*H !password=______", 4619a747e4fSDavid du Colombier safe.authid, safe.authdom, DESKEYLEN, safe.machkey); 4629a747e4fSDavid du Colombier writehostowner(safe.authid); 4639a747e4fSDavid du Colombier 4649a747e4fSDavid du Colombier return s; 4659a747e4fSDavid du Colombier } 4669a747e4fSDavid du Colombier 4679a747e4fSDavid du Colombier int 4689a747e4fSDavid du Colombier isclient(char *role) 4699a747e4fSDavid du Colombier { 4709a747e4fSDavid du Colombier if(role == nil){ 4719a747e4fSDavid du Colombier werrstr("role not specified"); 4729a747e4fSDavid du Colombier return -1; 4739a747e4fSDavid du Colombier } 4749a747e4fSDavid du Colombier if(strcmp(role, "server") == 0) 4759a747e4fSDavid du Colombier return 0; 4769a747e4fSDavid du Colombier if(strcmp(role, "client") == 0) 4779a747e4fSDavid du Colombier return 1; 4789a747e4fSDavid du Colombier werrstr("unknown role %q", role); 4799a747e4fSDavid du Colombier return -1; 4809a747e4fSDavid du Colombier } 4819a747e4fSDavid du Colombier 4829a747e4fSDavid du Colombier static int 4839a747e4fSDavid du Colombier hasname(Attr *a0, Attr *a1, char *name) 4849a747e4fSDavid du Colombier { 4859a747e4fSDavid du Colombier return _findattr(a0, name) || _findattr(a1, name); 4869a747e4fSDavid du Colombier } 4879a747e4fSDavid du Colombier 4889a747e4fSDavid du Colombier static int 4899a747e4fSDavid du Colombier hasnameval(Attr *a0, Attr *a1, char *name, char *val) 4909a747e4fSDavid du Colombier { 4919a747e4fSDavid du Colombier Attr *a; 4929a747e4fSDavid du Colombier 4939a747e4fSDavid du Colombier for(a=_findattr(a0, name); a; a=_findattr(a->next, name)) 4949a747e4fSDavid du Colombier if(strcmp(s_to_c(a->val), val) == 0) 4959a747e4fSDavid du Colombier return 1; 4969a747e4fSDavid du Colombier for(a=_findattr(a1, name); a; a=_findattr(a->next, name)) 4979a747e4fSDavid du Colombier if(strcmp(s_to_c(a->val), val) == 0) 4989a747e4fSDavid du Colombier return 1; 4999a747e4fSDavid du Colombier return 0; 5009a747e4fSDavid du Colombier } 5019a747e4fSDavid du Colombier 5029a747e4fSDavid du Colombier int 5039a747e4fSDavid du Colombier matchattr(Attr *pat, Attr *a0, Attr *a1) 5049a747e4fSDavid du Colombier { 5059a747e4fSDavid du Colombier int type; 5069a747e4fSDavid du Colombier 5079a747e4fSDavid du Colombier for(; pat; pat=pat->next){ 5089a747e4fSDavid du Colombier type = pat->type; 5099a747e4fSDavid du Colombier if(ignoreattr(s_to_c(pat->name))) 5109a747e4fSDavid du Colombier type = AttrDefault; 5119a747e4fSDavid du Colombier switch(type){ 5129a747e4fSDavid du Colombier case AttrQuery: /* name=something be present */ 5139a747e4fSDavid du Colombier if(!hasname(a0, a1, s_to_c(pat->name))) 5149a747e4fSDavid du Colombier return 0; 5159a747e4fSDavid du Colombier break; 5169a747e4fSDavid du Colombier case AttrNameval: /* name=val must be present */ 5179a747e4fSDavid du Colombier if(!hasnameval(a0, a1, s_to_c(pat->name), s_to_c(pat->val))) 5189a747e4fSDavid du Colombier return 0; 5199a747e4fSDavid du Colombier break; 5209a747e4fSDavid du Colombier case AttrDefault: /* name=val must be present if name=anything is present */ 5219a747e4fSDavid du Colombier if(hasname(a0, a1, s_to_c(pat->name)) && !hasnameval(a0, a1, s_to_c(pat->name), s_to_c(pat->val))) 5229a747e4fSDavid du Colombier return 0; 5239a747e4fSDavid du Colombier break; 5249a747e4fSDavid du Colombier } 5259a747e4fSDavid du Colombier } 5269a747e4fSDavid du Colombier return 1; 5279a747e4fSDavid du Colombier } 5289a747e4fSDavid du Colombier 5299a747e4fSDavid du Colombier void 5309a747e4fSDavid du Colombier memrandom(void *p, int n) 5319a747e4fSDavid du Colombier { 5329a747e4fSDavid du Colombier uchar *cp; 5339a747e4fSDavid du Colombier 5349a747e4fSDavid du Colombier for(cp = (uchar*)p; n > 0; n--) 5359a747e4fSDavid du Colombier *cp++ = fastrand(); 5369a747e4fSDavid du Colombier } 5379a747e4fSDavid du Colombier 5389a747e4fSDavid du Colombier /* 5393ff48bf5SDavid du Colombier * keep caphash fd open since opens of it could be disabled 5403ff48bf5SDavid du Colombier */ 5413ff48bf5SDavid du Colombier static int caphashfd; 5423ff48bf5SDavid du Colombier 5433ff48bf5SDavid du Colombier void 5443ff48bf5SDavid du Colombier initcap(void) 5453ff48bf5SDavid du Colombier { 5463ff48bf5SDavid du Colombier caphashfd = open("#¤/caphash", OWRITE); 547*d9306527SDavid du Colombier // if(caphashfd < 0) 548*d9306527SDavid du Colombier // fprint(2, "%s: opening #¤/caphash: %r\n", argv0); 5493ff48bf5SDavid du Colombier } 5503ff48bf5SDavid du Colombier 5513ff48bf5SDavid du Colombier /* 5529a747e4fSDavid du Colombier * create a change uid capability 5539a747e4fSDavid du Colombier */ 5549a747e4fSDavid du Colombier char* 5553ff48bf5SDavid du Colombier mkcap(char *from, char *to) 5569a747e4fSDavid du Colombier { 5579a747e4fSDavid du Colombier uchar rand[20]; 5589a747e4fSDavid du Colombier char *cap; 5599a747e4fSDavid du Colombier char *key; 5603ff48bf5SDavid du Colombier int nfrom, nto; 5619a747e4fSDavid du Colombier uchar hash[SHA1dlen]; 5629a747e4fSDavid du Colombier 5633ff48bf5SDavid du Colombier if(caphashfd < 0) 5649a747e4fSDavid du Colombier return nil; 5659a747e4fSDavid du Colombier 5669a747e4fSDavid du Colombier /* create the capability */ 5673ff48bf5SDavid du Colombier nto = strlen(to); 5683ff48bf5SDavid du Colombier nfrom = strlen(from); 5693ff48bf5SDavid du Colombier cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1); 5703ff48bf5SDavid du Colombier sprint(cap, "%s@%s", from, to); 5719a747e4fSDavid du Colombier memrandom(rand, sizeof(rand)); 5723ff48bf5SDavid du Colombier key = cap+nfrom+1+nto+1; 5739a747e4fSDavid du Colombier enc64(key, sizeof(rand)*3, rand, sizeof(rand)); 5749a747e4fSDavid du Colombier 5759a747e4fSDavid du Colombier /* hash the capability */ 5763ff48bf5SDavid du Colombier hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil); 5779a747e4fSDavid du Colombier 5789a747e4fSDavid du Colombier /* give the kernel the hash */ 5793ff48bf5SDavid du Colombier key[-1] = '@'; 5803ff48bf5SDavid du Colombier if(write(caphashfd, hash, SHA1dlen) < 0){ 5819a747e4fSDavid du Colombier free(cap); 5829a747e4fSDavid du Colombier return nil; 5839a747e4fSDavid du Colombier } 5849a747e4fSDavid du Colombier 5859a747e4fSDavid du Colombier return cap; 5869a747e4fSDavid du Colombier } 5879a747e4fSDavid du Colombier 5889a747e4fSDavid du Colombier int 5899a747e4fSDavid du Colombier phaseerror(Fsstate *s, char *op) 5909a747e4fSDavid du Colombier { 5919a747e4fSDavid du Colombier char tmp[32]; 5929a747e4fSDavid du Colombier 5939a747e4fSDavid du Colombier werrstr("protocol phase error: %s in state %s", op, phasename(s, s->phase, tmp)); 5949a747e4fSDavid du Colombier return RpcPhase; 5959a747e4fSDavid du Colombier } 5969a747e4fSDavid du Colombier 5979a747e4fSDavid du Colombier char* 5989a747e4fSDavid du Colombier phasename(Fsstate *fss, int phase, char *tmp) 5999a747e4fSDavid du Colombier { 6009a747e4fSDavid du Colombier char *name; 6019a747e4fSDavid du Colombier 6029a747e4fSDavid du Colombier if(fss->phase == Broken) 6039a747e4fSDavid du Colombier name = "Broken"; 6049a747e4fSDavid du Colombier else if(phase == Established) 6059a747e4fSDavid du Colombier name = "Established"; 6069a747e4fSDavid du Colombier else if(phase == Notstarted) 6079a747e4fSDavid du Colombier name = "Notstarted"; 6089a747e4fSDavid du Colombier else if(phase < 0 || phase >= fss->maxphase 6099a747e4fSDavid du Colombier || (name = fss->phasename[phase]) == nil){ 6109a747e4fSDavid du Colombier sprint(tmp, "%d", phase); 6119a747e4fSDavid du Colombier name = tmp; 6129a747e4fSDavid du Colombier } 6139a747e4fSDavid du Colombier return name; 6149a747e4fSDavid du Colombier } 6159a747e4fSDavid du Colombier 6169a747e4fSDavid du Colombier static int 6179a747e4fSDavid du Colombier outin(char *prompt, char *def, int len) 6189a747e4fSDavid du Colombier { 6199a747e4fSDavid du Colombier String *s; 6209a747e4fSDavid du Colombier 6219a747e4fSDavid du Colombier s = readcons(prompt, def, 0); 6229a747e4fSDavid du Colombier if(s == nil) 6239a747e4fSDavid du Colombier return -1; 6249a747e4fSDavid du Colombier if(s_to_c(s) == nil) 6259a747e4fSDavid du Colombier sysfatal("s_to_c(s)==nil???"); 6269a747e4fSDavid du Colombier strncpy(def, s_to_c(s), len); 6279a747e4fSDavid du Colombier def[len-1] = 0; 6289a747e4fSDavid du Colombier s_free(s); 6299a747e4fSDavid du Colombier return strlen(def); 6309a747e4fSDavid du Colombier } 6319a747e4fSDavid du Colombier 6329a747e4fSDavid du Colombier /* 6339a747e4fSDavid du Colombier * get host owner and set it 6349a747e4fSDavid du Colombier */ 6359a747e4fSDavid du Colombier void 6369a747e4fSDavid du Colombier promptforhostowner(void) 6379a747e4fSDavid du Colombier { 6389a747e4fSDavid du Colombier char owner[64], *p; 6399a747e4fSDavid du Colombier 6409a747e4fSDavid du Colombier /* hack for bitsy; can't prompt during boot */ 6419a747e4fSDavid du Colombier if(p = getenv("user")){ 6429a747e4fSDavid du Colombier writehostowner(p); 643*d9306527SDavid du Colombier free(p); 6449a747e4fSDavid du Colombier return; 6459a747e4fSDavid du Colombier } 646*d9306527SDavid du Colombier free(p); 6479a747e4fSDavid du Colombier 6489a747e4fSDavid du Colombier strcpy(owner, "none"); 6499a747e4fSDavid du Colombier do{ 6509a747e4fSDavid du Colombier outin("user", owner, sizeof(owner)); 6519a747e4fSDavid du Colombier } while(*owner == 0); 6529a747e4fSDavid du Colombier writehostowner(owner); 6539a747e4fSDavid du Colombier } 6549a747e4fSDavid du Colombier 6559a747e4fSDavid du Colombier /* 6569a747e4fSDavid du Colombier * prompt for a string with a possible default response 6579a747e4fSDavid du Colombier */ 6589a747e4fSDavid du Colombier String* 6599a747e4fSDavid du Colombier readcons(char *prompt, char *def, int raw) 6609a747e4fSDavid du Colombier { 6619a747e4fSDavid du Colombier int fdin, fdout, ctl, n; 6629a747e4fSDavid du Colombier char line[10]; 6639a747e4fSDavid du Colombier String *s = s_new(); 6649a747e4fSDavid du Colombier 6659a747e4fSDavid du Colombier fdin = open("/dev/cons", OREAD); 6669a747e4fSDavid du Colombier if(fdin < 0) 6679a747e4fSDavid du Colombier fdin = 0; 6689a747e4fSDavid du Colombier fdout = open("/dev/cons", OWRITE); 6699a747e4fSDavid du Colombier if(fdout < 0) 6709a747e4fSDavid du Colombier fdout = 1; 6719a747e4fSDavid du Colombier if(def != nil) 6729a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 6739a747e4fSDavid du Colombier else 6749a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 6759a747e4fSDavid du Colombier if(raw){ 6769a747e4fSDavid du Colombier ctl = open("/dev/consctl", OWRITE); 6779a747e4fSDavid du Colombier if(ctl >= 0) 6789a747e4fSDavid du Colombier write(ctl, "rawon", 5); 6799a747e4fSDavid du Colombier } else 6809a747e4fSDavid du Colombier ctl = -1; 6819a747e4fSDavid du Colombier for(;;){ 6829a747e4fSDavid du Colombier n = read(fdin, line, 1); 6839a747e4fSDavid du Colombier if(n == 0){ 6849a747e4fSDavid du Colombier Error: 6859a747e4fSDavid du Colombier close(fdin); 6869a747e4fSDavid du Colombier close(fdout); 6879a747e4fSDavid du Colombier if(ctl >= 0) 6889a747e4fSDavid du Colombier close(ctl); 6899a747e4fSDavid du Colombier s_free(s); 6909a747e4fSDavid du Colombier return nil; 6919a747e4fSDavid du Colombier } 6929a747e4fSDavid du Colombier if(n < 0) 6939a747e4fSDavid du Colombier goto Error; 6949a747e4fSDavid du Colombier if(line[0] == 0x7f) 6959a747e4fSDavid du Colombier goto Error; 6969a747e4fSDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){ 6979a747e4fSDavid du Colombier if(raw){ 6989a747e4fSDavid du Colombier write(ctl, "rawoff", 6); 6999a747e4fSDavid du Colombier write(fdout, "\n", 1); 7009a747e4fSDavid du Colombier } 7019a747e4fSDavid du Colombier close(ctl); 7029a747e4fSDavid du Colombier close(fdin); 7039a747e4fSDavid du Colombier close(fdout); 7049a747e4fSDavid du Colombier s_terminate(s); 7059a747e4fSDavid du Colombier if(*s_to_c(s) == 0 && def != nil) 7069a747e4fSDavid du Colombier s_append(s, def); 7079a747e4fSDavid du Colombier return s; 7089a747e4fSDavid du Colombier } 7099a747e4fSDavid du Colombier if(line[0] == '\b'){ 7109a747e4fSDavid du Colombier if(s_len(s) > 0) 7119a747e4fSDavid du Colombier s->ptr--; 7129a747e4fSDavid du Colombier } else if(line[0] == 0x15) { /* ^U: line kill */ 7139a747e4fSDavid du Colombier s_reset(s); 7149a747e4fSDavid du Colombier } else { 7159a747e4fSDavid du Colombier s_putc(s, line[0]); 7169a747e4fSDavid du Colombier } 7179a747e4fSDavid du Colombier } 7189a747e4fSDavid du Colombier return s; /* how does this happen */ 7199a747e4fSDavid du Colombier } 7209a747e4fSDavid du Colombier 7219a747e4fSDavid du Colombier /* 7229a747e4fSDavid du Colombier * Insert a key into the keyring. 7239a747e4fSDavid du Colombier * If the public attributes are identical to some other key, replace that one. 7249a747e4fSDavid du Colombier */ 7259a747e4fSDavid du Colombier int 7269a747e4fSDavid du Colombier replacekey(Key *kn) 7279a747e4fSDavid du Colombier { 7289a747e4fSDavid du Colombier int i; 7299a747e4fSDavid du Colombier Key *k; 7309a747e4fSDavid du Colombier 7319a747e4fSDavid du Colombier for(i=0; i<ring->nkey; i++){ 7329a747e4fSDavid du Colombier k = ring->key[i]; 7339a747e4fSDavid du Colombier if(matchattr(kn->attr, k->attr, nil) && matchattr(k->attr, kn->attr, nil)){ 7349a747e4fSDavid du Colombier closekey(k); 7359a747e4fSDavid du Colombier kn->ref++; 7369a747e4fSDavid du Colombier ring->key[i] = kn; 7379a747e4fSDavid du Colombier return 0; 7389a747e4fSDavid du Colombier } 7399a747e4fSDavid du Colombier } 7409a747e4fSDavid du Colombier if(ring->nkey%16 == 0) 7419a747e4fSDavid du Colombier ring->key = erealloc(ring->key, (ring->nkey+16)*sizeof(ring->key[0])); 7429a747e4fSDavid du Colombier kn->ref++; 7439a747e4fSDavid du Colombier ring->key[ring->nkey++] = kn; 7449a747e4fSDavid du Colombier return 0; 7459a747e4fSDavid du Colombier } 7469a747e4fSDavid du Colombier 7479a747e4fSDavid du Colombier char* 7489a747e4fSDavid du Colombier safecpy(char *to, char *from, int n) 7499a747e4fSDavid du Colombier { 7509a747e4fSDavid du Colombier memset(to, 0, n); 7519a747e4fSDavid du Colombier if(n == 1) 7529a747e4fSDavid du Colombier return to; 7539a747e4fSDavid du Colombier if(from==nil) 7549a747e4fSDavid du Colombier sysfatal("safecpy called with from==nil, pc=%lux\n", 7559a747e4fSDavid du Colombier getcallerpc(&to)); 7569a747e4fSDavid du Colombier strncpy(to, from, n-1); 7579a747e4fSDavid du Colombier return to; 7589a747e4fSDavid du Colombier } 7599a747e4fSDavid du Colombier 7609a747e4fSDavid du Colombier Attr* 7619a747e4fSDavid du Colombier setattr(Attr *a, char *fmt, ...) 7629a747e4fSDavid du Colombier { 7639a747e4fSDavid du Colombier char buf[1024]; 7649a747e4fSDavid du Colombier va_list arg; 7659a747e4fSDavid du Colombier Attr *b; 7669a747e4fSDavid du Colombier 7679a747e4fSDavid du Colombier va_start(arg, fmt); 7689a747e4fSDavid du Colombier vseprint(buf, buf+sizeof buf, fmt, arg); 7699a747e4fSDavid du Colombier va_end(arg); 7709a747e4fSDavid du Colombier b = _parseattr(buf); 7719a747e4fSDavid du Colombier a = setattrs(a, b); 7729a747e4fSDavid du Colombier setmalloctag(a, getcallerpc(&a)); 7739a747e4fSDavid du Colombier _freeattr(b); 7749a747e4fSDavid du Colombier return a; 7759a747e4fSDavid du Colombier } 7769a747e4fSDavid du Colombier 7779a747e4fSDavid du Colombier /* 7789a747e4fSDavid du Colombier * add attributes in list b to list a. If any attributes are in 7799a747e4fSDavid du Colombier * both lists, replace those in a by those in b. 7809a747e4fSDavid du Colombier */ 7819a747e4fSDavid du Colombier Attr* 7829a747e4fSDavid du Colombier setattrs(Attr *a, Attr *b) 7839a747e4fSDavid du Colombier { 7849a747e4fSDavid du Colombier int found; 7859a747e4fSDavid du Colombier Attr **l, *freea; 7869a747e4fSDavid du Colombier 7879a747e4fSDavid du Colombier for(; b; b=b->next){ 7889a747e4fSDavid du Colombier found = 0; 7899a747e4fSDavid du Colombier for(l=&a; *l; ){ 7909a747e4fSDavid du Colombier if(strcmp(s_to_c(b->name), s_to_c((*l)->name)) == 0){ 7919a747e4fSDavid du Colombier switch(b->type){ 7929a747e4fSDavid du Colombier case AttrNameval: 7939a747e4fSDavid du Colombier if(!found){ 7949a747e4fSDavid du Colombier found = 1; 7959a747e4fSDavid du Colombier s_free((*l)->val); 7969a747e4fSDavid du Colombier (*l)->val = s_incref(b->val); 7979a747e4fSDavid du Colombier (*l)->type = AttrNameval; 7989a747e4fSDavid du Colombier l = &(*l)->next; 7999a747e4fSDavid du Colombier }else{ 8009a747e4fSDavid du Colombier freea = *l; 8019a747e4fSDavid du Colombier *l = (*l)->next; 8029a747e4fSDavid du Colombier freea->next = nil; 8039a747e4fSDavid du Colombier _freeattr(freea); 8049a747e4fSDavid du Colombier } 8059a747e4fSDavid du Colombier break; 8069a747e4fSDavid du Colombier case AttrQuery: 8079a747e4fSDavid du Colombier found++; 8089a747e4fSDavid du Colombier break; 8099a747e4fSDavid du Colombier } 8109a747e4fSDavid du Colombier }else 8119a747e4fSDavid du Colombier l = &(*l)->next; 8129a747e4fSDavid du Colombier } 8139a747e4fSDavid du Colombier if(found == 0){ 8149a747e4fSDavid du Colombier *l = _mkattr(b->type, s_to_c(b->name), s_to_c(b->val), nil); 8159a747e4fSDavid du Colombier setmalloctag(*l, getcallerpc(&a)); 8169a747e4fSDavid du Colombier } 8179a747e4fSDavid du Colombier } 8189a747e4fSDavid du Colombier return a; 8199a747e4fSDavid du Colombier } 8209a747e4fSDavid du Colombier 8219a747e4fSDavid du Colombier void 8229a747e4fSDavid du Colombier setmalloctaghere(void *v) 8239a747e4fSDavid du Colombier { 8249a747e4fSDavid du Colombier setmalloctag(v, getcallerpc(&v)); 8259a747e4fSDavid du Colombier } 8269a747e4fSDavid du Colombier 8279a747e4fSDavid du Colombier Attr* 8289a747e4fSDavid du Colombier sortattr(Attr *a) 8299a747e4fSDavid du Colombier { 8309a747e4fSDavid du Colombier int i; 8319a747e4fSDavid du Colombier Attr *anext, *a0, *a1, **l; 8329a747e4fSDavid du Colombier 8339a747e4fSDavid du Colombier if(a == nil || a->next == nil) 8349a747e4fSDavid du Colombier return a; 8359a747e4fSDavid du Colombier 8369a747e4fSDavid du Colombier /* cut list in halves */ 8379a747e4fSDavid du Colombier a0 = nil; 8389a747e4fSDavid du Colombier a1 = nil; 8399a747e4fSDavid du Colombier i = 0; 8409a747e4fSDavid du Colombier for(; a; a=anext){ 8419a747e4fSDavid du Colombier anext = a->next; 8429a747e4fSDavid du Colombier if(i++%2){ 8439a747e4fSDavid du Colombier a->next = a0; 8449a747e4fSDavid du Colombier a0 = a; 8459a747e4fSDavid du Colombier }else{ 8469a747e4fSDavid du Colombier a->next = a1; 8479a747e4fSDavid du Colombier a1 = a; 8489a747e4fSDavid du Colombier } 8499a747e4fSDavid du Colombier } 8509a747e4fSDavid du Colombier 8519a747e4fSDavid du Colombier /* sort */ 8529a747e4fSDavid du Colombier a0 = sortattr(a0); 8539a747e4fSDavid du Colombier a1 = sortattr(a1); 8549a747e4fSDavid du Colombier 8559a747e4fSDavid du Colombier /* merge */ 8569a747e4fSDavid du Colombier l = &a; 8579a747e4fSDavid du Colombier while(a0 || a1){ 8589a747e4fSDavid du Colombier if(a1==nil){ 8599a747e4fSDavid du Colombier anext = a0; 8609a747e4fSDavid du Colombier a0 = a0->next; 8619a747e4fSDavid du Colombier }else if(a0==nil){ 8629a747e4fSDavid du Colombier anext = a1; 8639a747e4fSDavid du Colombier a1 = a1->next; 8649a747e4fSDavid du Colombier }else if(strcmp(s_to_c(a0->name), s_to_c(a1->name)) < 0){ 8659a747e4fSDavid du Colombier anext = a0; 8669a747e4fSDavid du Colombier a0 = a0->next; 8679a747e4fSDavid du Colombier }else{ 8689a747e4fSDavid du Colombier anext = a1; 8699a747e4fSDavid du Colombier a1 = a1->next; 8709a747e4fSDavid du Colombier } 8719a747e4fSDavid du Colombier *l = anext; 8729a747e4fSDavid du Colombier l = &(*l)->next; 8739a747e4fSDavid du Colombier } 8749a747e4fSDavid du Colombier *l = nil; 8759a747e4fSDavid du Colombier return a; 8769a747e4fSDavid du Colombier } 8779a747e4fSDavid du Colombier 8789a747e4fSDavid du Colombier int 8799a747e4fSDavid du Colombier toosmall(Fsstate *fss, uint n) 8809a747e4fSDavid du Colombier { 8819a747e4fSDavid du Colombier fss->rpc.nwant = n; 8829a747e4fSDavid du Colombier return RpcToosmall; 8839a747e4fSDavid du Colombier } 8849a747e4fSDavid du Colombier 8859a747e4fSDavid du Colombier void 8869a747e4fSDavid du Colombier writehostowner(char *owner) 8879a747e4fSDavid du Colombier { 8889a747e4fSDavid du Colombier int fd; 8899a747e4fSDavid du Colombier char *s; 8909a747e4fSDavid du Colombier 8919a747e4fSDavid du Colombier if((s = strchr(owner,'@')) != nil){ 8929a747e4fSDavid du Colombier *s++ = 0; 8939a747e4fSDavid du Colombier strncpy(secstore, s, (sizeof secstore)-1); 8949a747e4fSDavid du Colombier } 8959a747e4fSDavid du Colombier fd = open("#c/hostowner", OWRITE); 8969a747e4fSDavid du Colombier if(fd >= 0){ 8979a747e4fSDavid du Colombier if(fprint(fd, "%s", owner) < 0) 8989a747e4fSDavid du Colombier fprint(2, "setting #c/hostowner to %q: %r\n", owner); 8999a747e4fSDavid du Colombier close(fd); 9009a747e4fSDavid du Colombier } 9019a747e4fSDavid du Colombier } 9029a747e4fSDavid du Colombier 9035d459b5aSDavid du Colombier int 9045d459b5aSDavid du Colombier attrnamefmt(Fmt *fmt) 9055d459b5aSDavid du Colombier { 9065d459b5aSDavid du Colombier char *b, buf[1024], *ebuf; 9075d459b5aSDavid du Colombier Attr *a; 9085d459b5aSDavid du Colombier 9095d459b5aSDavid du Colombier ebuf = buf+sizeof buf; 9105d459b5aSDavid du Colombier b = buf; 9115d459b5aSDavid du Colombier strcpy(buf, " "); 9125d459b5aSDavid du Colombier for(a=va_arg(fmt->args, Attr*); a; a=a->next){ 9135d459b5aSDavid du Colombier if(a->name == nil) 9145d459b5aSDavid du Colombier continue; 9155d459b5aSDavid du Colombier b = seprint(b, ebuf, " %q?", s_to_c(a->name)); 9165d459b5aSDavid du Colombier } 9175d459b5aSDavid du Colombier return fmtstrcpy(fmt, buf+1); 9185d459b5aSDavid du Colombier } 919