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 { 28b05f4f54SDavid du Colombier int fd, vanilla; 299a747e4fSDavid du Colombier 30b05f4f54SDavid du Colombier vanilla = net==nil || strcmp(net, "/net")==0; 31b05f4f54SDavid du Colombier 32b05f4f54SDavid du Colombier if(!vanilla || bindnetcs()>=0) 33b05f4f54SDavid du Colombier return authdial(net, authdom); 34b05f4f54SDavid du Colombier 35b05f4f54SDavid du Colombier /* 36b05f4f54SDavid du Colombier * If we failed to mount /srv/cs, assume that 37b05f4f54SDavid du Colombier * we're still bootstrapping the system and dial 38b05f4f54SDavid du Colombier * the one auth server passed to us on the command line. 39b05f4f54SDavid du Colombier * In normal operation, it is important *not* to do this, 40b05f4f54SDavid du Colombier * because the bootstrap auth server is only good for 41b05f4f54SDavid du Colombier * a single auth domain. 42b05f4f54SDavid du Colombier * 43b05f4f54SDavid du Colombier * The ticket request code should really check the 44b05f4f54SDavid du Colombier * remote authentication domain too. 45b05f4f54SDavid du Colombier */ 469a747e4fSDavid du Colombier 479a747e4fSDavid du Colombier /* use the auth sever passed to us as an arg */ 489a747e4fSDavid du Colombier if(authaddr == nil) 499a747e4fSDavid du Colombier return -1; 509a747e4fSDavid du Colombier fd = dial(netmkaddr(authaddr, "il", "566"), 0, 0, 0); 519a747e4fSDavid du Colombier if(fd >= 0) 529a747e4fSDavid du Colombier return fd; 539a747e4fSDavid du Colombier return dial(netmkaddr(authaddr, "tcp", "567"), 0, 0, 0); 549a747e4fSDavid du Colombier } 559a747e4fSDavid du Colombier 569a747e4fSDavid du Colombier int 579a747e4fSDavid du Colombier secdial(void) 589a747e4fSDavid du Colombier { 599a747e4fSDavid du Colombier char *p, buf[80], *f[3]; 609a747e4fSDavid du Colombier int fd, nf; 619a747e4fSDavid du Colombier 629a747e4fSDavid du Colombier p = secstore; /* take it from writehostowner, if set there */ 639a747e4fSDavid du Colombier if(*p == 0) /* else use the authserver */ 649a747e4fSDavid du Colombier p = "$auth"; 659a747e4fSDavid du Colombier 669a747e4fSDavid du Colombier if(bindnetcs() >= 0) 679a747e4fSDavid du Colombier return dial(netmkaddr(p, "net", "secstore"), 0, 0, 0); 689a747e4fSDavid du Colombier 699a747e4fSDavid du Colombier /* translate $auth ourselves. 709a747e4fSDavid du Colombier * authaddr is something like il!host!566 or tcp!host!567. 719a747e4fSDavid du Colombier * extract host, accounting for a change of format to something 729a747e4fSDavid du Colombier * like il!host or tcp!host or host. 739a747e4fSDavid du Colombier */ 749a747e4fSDavid du Colombier if(strcmp(p, "$auth")==0){ 759a747e4fSDavid du Colombier if(authaddr == nil) 769a747e4fSDavid du Colombier return -1; 779a747e4fSDavid du Colombier safecpy(buf, authaddr, sizeof buf); 789a747e4fSDavid du Colombier nf = getfields(buf, f, nelem(f), 0, "!"); 799a747e4fSDavid du Colombier switch(nf){ 809a747e4fSDavid du Colombier default: 819a747e4fSDavid du Colombier return -1; 829a747e4fSDavid du Colombier case 1: 839a747e4fSDavid du Colombier p = f[0]; 849a747e4fSDavid du Colombier break; 859a747e4fSDavid du Colombier case 2: 869a747e4fSDavid du Colombier case 3: 879a747e4fSDavid du Colombier p = f[1]; 889a747e4fSDavid du Colombier break; 899a747e4fSDavid du Colombier } 909a747e4fSDavid du Colombier } 919a747e4fSDavid du Colombier fd = dial(netmkaddr(p, "tcp", "5356"), 0, 0, 0); 929a747e4fSDavid du Colombier if(fd >= 0) 939a747e4fSDavid du Colombier return fd; 949a747e4fSDavid du Colombier return -1; 959a747e4fSDavid du Colombier } 969a747e4fSDavid du Colombier /* 979a747e4fSDavid du Colombier * prompt user for a key. don't care about memory leaks, runs standalone 989a747e4fSDavid du Colombier */ 999a747e4fSDavid du Colombier static Attr* 1009a747e4fSDavid du Colombier promptforkey(char *params) 1019a747e4fSDavid du Colombier { 1029a747e4fSDavid du Colombier char *v; 1039a747e4fSDavid du Colombier int fd; 1049a747e4fSDavid du Colombier Attr *a, *attr; 1059a747e4fSDavid du Colombier char *def; 1069a747e4fSDavid du Colombier 1079a747e4fSDavid du Colombier fd = open("/dev/cons", ORDWR); 1089a747e4fSDavid du Colombier if(fd < 0) 1099a747e4fSDavid du Colombier sysfatal("opening /dev/cons: %r"); 1109a747e4fSDavid du Colombier 1119a747e4fSDavid du Colombier attr = _parseattr(params); 1129a747e4fSDavid du Colombier fprint(fd, "\n!Adding key:"); 1139a747e4fSDavid du Colombier for(a=attr; a; a=a->next) 1142ebbfa15SDavid du Colombier if(a->type != AttrQuery && a->name[0] != '!') 1152ebbfa15SDavid du Colombier fprint(fd, " %q=%q", a->name, a->val); 1169a747e4fSDavid du Colombier fprint(fd, "\n"); 1179a747e4fSDavid du Colombier 1189a747e4fSDavid du Colombier for(a=attr; a; a=a->next){ 1192ebbfa15SDavid du Colombier v = a->name; 1209a747e4fSDavid du Colombier if(a->type != AttrQuery || v[0]=='!') 1219a747e4fSDavid du Colombier continue; 1229a747e4fSDavid du Colombier def = nil; 1239a747e4fSDavid du Colombier if(strcmp(v, "user") == 0) 1249a747e4fSDavid du Colombier def = getuser(); 1259a747e4fSDavid du Colombier a->val = readcons(v, def, 0); 1269a747e4fSDavid du Colombier if(a->val == nil) 1279a747e4fSDavid du Colombier sysfatal("user terminated key input"); 1289a747e4fSDavid du Colombier a->type = AttrNameval; 1299a747e4fSDavid du Colombier } 1309a747e4fSDavid du Colombier for(a=attr; a; a=a->next){ 1312ebbfa15SDavid du Colombier v = a->name; 1329a747e4fSDavid du Colombier if(a->type != AttrQuery || v[0]!='!') 1339a747e4fSDavid du Colombier continue; 1349a747e4fSDavid du Colombier def = nil; 1359a747e4fSDavid du Colombier if(strcmp(v+1, "user") == 0) 1369a747e4fSDavid du Colombier def = getuser(); 1379a747e4fSDavid du Colombier a->val = readcons(v+1, def, 1); 1389a747e4fSDavid du Colombier if(a->val == nil) 1399a747e4fSDavid du Colombier sysfatal("user terminated key input"); 1409a747e4fSDavid du Colombier a->type = AttrNameval; 1419a747e4fSDavid du Colombier } 1429a747e4fSDavid du Colombier fprint(fd, "!\n"); 1439a747e4fSDavid du Colombier close(fd); 1449a747e4fSDavid du Colombier return attr; 1459a747e4fSDavid du Colombier } 1469a747e4fSDavid du Colombier 1479a747e4fSDavid du Colombier /* 1489a747e4fSDavid du Colombier * send a key to the mounted factotum 1499a747e4fSDavid du Colombier */ 1509a747e4fSDavid du Colombier static int 1519a747e4fSDavid du Colombier sendkey(Attr *attr) 1529a747e4fSDavid du Colombier { 1539a747e4fSDavid du Colombier int fd, rv; 1549a747e4fSDavid du Colombier char buf[1024]; 1559a747e4fSDavid du Colombier 1569a747e4fSDavid du Colombier fd = open("/mnt/factotum/ctl", ORDWR); 1579a747e4fSDavid du Colombier if(fd < 0) 1589a747e4fSDavid du Colombier sysfatal("opening /mnt/factotum/ctl: %r"); 1599a747e4fSDavid du Colombier rv = fprint(fd, "key %A\n", attr); 1609a747e4fSDavid du Colombier read(fd, buf, sizeof buf); 1619a747e4fSDavid du Colombier close(fd); 1629a747e4fSDavid du Colombier return rv; 1639a747e4fSDavid du Colombier } 1649a747e4fSDavid du Colombier 1659a747e4fSDavid du Colombier /* askuser */ 1669a747e4fSDavid du Colombier void 1679a747e4fSDavid du Colombier askuser(char *params) 1689a747e4fSDavid du Colombier { 1699a747e4fSDavid du Colombier Attr *attr; 1709a747e4fSDavid du Colombier 1719a747e4fSDavid du Colombier attr = promptforkey(params); 1729a747e4fSDavid du Colombier if(attr == nil) 1739a747e4fSDavid du Colombier sysfatal("no key supplied"); 1749a747e4fSDavid du Colombier if(sendkey(attr) < 0) 1759a747e4fSDavid du Colombier sysfatal("sending key to factotum: %r"); 1769a747e4fSDavid du Colombier } 1779a747e4fSDavid du Colombier 1789a747e4fSDavid du Colombier ulong conftaggen; 1799a747e4fSDavid du Colombier int 1809a747e4fSDavid du Colombier canusekey(Fsstate *fss, Key *k) 1819a747e4fSDavid du Colombier { 1829a747e4fSDavid du Colombier int i; 1839a747e4fSDavid du Colombier 1842ebbfa15SDavid du Colombier if(_strfindattr(k->attr, "confirm")){ 1859a747e4fSDavid du Colombier for(i=0; i<fss->nconf; i++) 1869a747e4fSDavid du Colombier if(fss->conf[i].key == k) 1879a747e4fSDavid du Colombier return fss->conf[i].canuse; 1889a747e4fSDavid du Colombier if(fss->nconf%16 == 0) 1899a747e4fSDavid du Colombier fss->conf = erealloc(fss->conf, (fss->nconf+16)*(sizeof(fss->conf[0]))); 1909a747e4fSDavid du Colombier fss->conf[fss->nconf].key = k; 1919a747e4fSDavid du Colombier k->ref++; 1929a747e4fSDavid du Colombier fss->conf[fss->nconf].canuse = -1; 1939a747e4fSDavid du Colombier fss->conf[fss->nconf].tag = conftaggen++; 1949a747e4fSDavid du Colombier fss->nconf++; 1959a747e4fSDavid du Colombier return -1; 1969a747e4fSDavid du Colombier } 1979a747e4fSDavid du Colombier return 1; 1989a747e4fSDavid du Colombier } 1999a747e4fSDavid du Colombier 2009a747e4fSDavid du Colombier /* closekey */ 2019a747e4fSDavid du Colombier void 2029a747e4fSDavid du Colombier closekey(Key *k) 2039a747e4fSDavid du Colombier { 2049a747e4fSDavid du Colombier if(k == nil) 2059a747e4fSDavid du Colombier return; 2069a747e4fSDavid du Colombier if(--k->ref != 0) 2079a747e4fSDavid du Colombier return; 208d9306527SDavid du Colombier if(k->proto && k->proto->closekey) 209d9306527SDavid du Colombier (*k->proto->closekey)(k); 2109a747e4fSDavid du Colombier _freeattr(k->attr); 2119a747e4fSDavid du Colombier _freeattr(k->privattr); 2129a747e4fSDavid du Colombier k->attr = (void*)~1; 2139a747e4fSDavid du Colombier k->privattr = (void*)~1; 2149a747e4fSDavid du Colombier k->proto = nil; 2159a747e4fSDavid du Colombier free(k); 2169a747e4fSDavid du Colombier } 2179a747e4fSDavid du Colombier 2189a747e4fSDavid du Colombier static uchar* 2199a747e4fSDavid du Colombier pstring(uchar *p, uchar *e, char *s) 2209a747e4fSDavid du Colombier { 2219a747e4fSDavid du Colombier uint n; 2229a747e4fSDavid du Colombier 2239a747e4fSDavid du Colombier if(p == nil) 2249a747e4fSDavid du Colombier return nil; 2259a747e4fSDavid du Colombier if(s == nil) 2269a747e4fSDavid du Colombier s = ""; 2279a747e4fSDavid du Colombier n = strlen(s); 2289a747e4fSDavid du Colombier if(p+n+BIT16SZ >= e) 2299a747e4fSDavid du Colombier return nil; 2309a747e4fSDavid du Colombier PBIT16(p, n); 2319a747e4fSDavid du Colombier p += BIT16SZ; 2329a747e4fSDavid du Colombier memmove(p, s, n); 2339a747e4fSDavid du Colombier p += n; 2349a747e4fSDavid du Colombier return p; 2359a747e4fSDavid du Colombier } 2369a747e4fSDavid du Colombier 2379a747e4fSDavid du Colombier static uchar* 2389a747e4fSDavid du Colombier pcarray(uchar *p, uchar *e, uchar *s, uint n) 2399a747e4fSDavid du Colombier { 2409a747e4fSDavid du Colombier if(p == nil) 2419a747e4fSDavid du Colombier return nil; 2429a747e4fSDavid du Colombier if(s == nil){ 2439a747e4fSDavid du Colombier if(n > 0) 2449a747e4fSDavid du Colombier sysfatal("pcarray"); 2459a747e4fSDavid du Colombier s = (uchar*)""; 2469a747e4fSDavid du Colombier } 2479a747e4fSDavid du Colombier if(p+n+BIT16SZ >= e) 2489a747e4fSDavid du Colombier return nil; 2499a747e4fSDavid du Colombier PBIT16(p, n); 2509a747e4fSDavid du Colombier p += BIT16SZ; 2519a747e4fSDavid du Colombier memmove(p, s, n); 2529a747e4fSDavid du Colombier p += n; 2539a747e4fSDavid du Colombier return p; 2549a747e4fSDavid du Colombier } 2559a747e4fSDavid du Colombier 2569a747e4fSDavid du Colombier uchar* 2579a747e4fSDavid du Colombier convAI2M(AuthInfo *ai, uchar *p, int n) 2589a747e4fSDavid du Colombier { 2599a747e4fSDavid du Colombier uchar *e = p+n; 2609a747e4fSDavid du Colombier 2619a747e4fSDavid du Colombier p = pstring(p, e, ai->cuid); 2629a747e4fSDavid du Colombier p = pstring(p, e, ai->suid); 2639a747e4fSDavid du Colombier p = pstring(p, e, ai->cap); 2649a747e4fSDavid du Colombier p = pcarray(p, e, ai->secret, ai->nsecret); 2659a747e4fSDavid du Colombier return p; 2669a747e4fSDavid du Colombier } 2679a747e4fSDavid du Colombier 2689a747e4fSDavid du Colombier int 2699a747e4fSDavid du Colombier failure(Fsstate *s, char *fmt, ...) 2709a747e4fSDavid du Colombier { 2719a747e4fSDavid du Colombier char e[ERRMAX]; 2729a747e4fSDavid du Colombier va_list arg; 2739a747e4fSDavid du Colombier 2749a747e4fSDavid du Colombier if(fmt == nil) 2759a747e4fSDavid du Colombier rerrstr(s->err, sizeof(s->err)); 2769a747e4fSDavid du Colombier else { 2779a747e4fSDavid du Colombier va_start(arg, fmt); 2789a747e4fSDavid du Colombier snprint(e, sizeof e, fmt, arg); 2799a747e4fSDavid du Colombier va_end(arg); 2809a747e4fSDavid du Colombier strecpy(s->err, s->err+sizeof(s->err), e); 281*87dfdc75SDavid du Colombier werrstr(e); 2829a747e4fSDavid du Colombier } 2839a747e4fSDavid du Colombier flog("%d: failure %s", s->seqnum, s->err); 2849a747e4fSDavid du Colombier return RpcFailure; 2859a747e4fSDavid du Colombier } 2869a747e4fSDavid du Colombier 2879a747e4fSDavid du Colombier static int 2889a747e4fSDavid du Colombier hasqueries(Attr *a) 2899a747e4fSDavid du Colombier { 2909a747e4fSDavid du Colombier for(; a; a=a->next) 2919a747e4fSDavid du Colombier if(a->type == AttrQuery) 2929a747e4fSDavid du Colombier return 1; 2939a747e4fSDavid du Colombier return 0; 2949a747e4fSDavid du Colombier } 2959a747e4fSDavid du Colombier 2969a747e4fSDavid du Colombier char *ignored[] = { 2979a747e4fSDavid du Colombier "role", 298260f7b65SDavid du Colombier "disabled", 2999a747e4fSDavid du Colombier }; 3009a747e4fSDavid du Colombier 3019a747e4fSDavid du Colombier static int 3029a747e4fSDavid du Colombier ignoreattr(char *s) 3039a747e4fSDavid du Colombier { 3049a747e4fSDavid du Colombier int i; 3059a747e4fSDavid du Colombier 3069a747e4fSDavid du Colombier for(i=0; i<nelem(ignored); i++) 3079a747e4fSDavid du Colombier if(strcmp(ignored[i], s)==0) 3089a747e4fSDavid du Colombier return 1; 3099a747e4fSDavid du Colombier return 0; 3109a747e4fSDavid du Colombier } 3119a747e4fSDavid du Colombier 312260f7b65SDavid du Colombier Keyinfo* 313260f7b65SDavid du Colombier mkkeyinfo(Keyinfo *k, Fsstate *fss, Attr *attr) 314260f7b65SDavid du Colombier { 315260f7b65SDavid du Colombier memset(k, 0, sizeof *k); 316260f7b65SDavid du Colombier k->fss = fss; 317260f7b65SDavid du Colombier k->user = fss->sysuser; 3186b8bc682SDavid du Colombier if(attr) 319260f7b65SDavid du Colombier k->attr = attr; 3206b8bc682SDavid du Colombier else 3216b8bc682SDavid du Colombier k->attr = fss->attr; 322260f7b65SDavid du Colombier return k; 323260f7b65SDavid du Colombier } 324260f7b65SDavid du Colombier 3259a747e4fSDavid du Colombier int 326260f7b65SDavid du Colombier findkey(Key **ret, Keyinfo *ki, char *fmt, ...) 3279a747e4fSDavid du Colombier { 3289a747e4fSDavid du Colombier int i, s, nmatch; 329260f7b65SDavid du Colombier char buf[1024], *p, *who; 3309a747e4fSDavid du Colombier va_list arg; 331260f7b65SDavid du Colombier Attr *a, *attr0, *attr1, *attr2, *attr3, **l; 3329a747e4fSDavid du Colombier Key *k; 3339a747e4fSDavid du Colombier 3349a747e4fSDavid du Colombier *ret = nil; 3359a747e4fSDavid du Colombier 336260f7b65SDavid du Colombier who = ki->user; 337260f7b65SDavid du Colombier attr0 = ki->attr; 3389a747e4fSDavid du Colombier if(fmt){ 3399a747e4fSDavid du Colombier va_start(arg, fmt); 3409a747e4fSDavid du Colombier vseprint(buf, buf+sizeof buf, fmt, arg); 3419a747e4fSDavid du Colombier va_end(arg); 3429a747e4fSDavid du Colombier attr1 = _parseattr(buf); 3439a747e4fSDavid du Colombier }else 3449a747e4fSDavid du Colombier attr1 = nil; 3459a747e4fSDavid du Colombier 346fb7f0c93SDavid du Colombier if(who && strcmp(who, owner) == 0) 347fb7f0c93SDavid du Colombier who = nil; 348fb7f0c93SDavid du Colombier 349fb7f0c93SDavid du Colombier if(who){ 350fb7f0c93SDavid du Colombier snprint(buf, sizeof buf, "owner=%q", who); 351fb7f0c93SDavid du Colombier attr2 = _parseattr(buf); 352fb7f0c93SDavid du Colombier attr3 = _parseattr("owner=*"); 353fb7f0c93SDavid du Colombier }else 354fb7f0c93SDavid du Colombier attr2 = attr3 = nil; 355fb7f0c93SDavid du Colombier 3562ebbfa15SDavid du Colombier p = _strfindattr(attr0, "proto"); 3579a747e4fSDavid du Colombier if(p == nil) 3582ebbfa15SDavid du Colombier p = _strfindattr(attr1, "proto"); 3599a747e4fSDavid du Colombier if(p && findproto(p) == nil){ 3609a747e4fSDavid du Colombier werrstr("unknown protocol %s", p); 3619a747e4fSDavid du Colombier _freeattr(attr1); 3624de34a7eSDavid du Colombier _freeattr(attr2); 3634de34a7eSDavid du Colombier _freeattr(attr3); 364260f7b65SDavid du Colombier return failure(ki->fss, nil); 3659a747e4fSDavid du Colombier } 3669a747e4fSDavid du Colombier 3679a747e4fSDavid du Colombier nmatch = 0; 3689a747e4fSDavid du Colombier for(i=0; i<ring->nkey; i++){ 3699a747e4fSDavid du Colombier k = ring->key[i]; 370260f7b65SDavid du Colombier if(_strfindattr(k->attr, "disabled") && !ki->usedisabled) 371260f7b65SDavid du Colombier continue; 3729a747e4fSDavid du Colombier if(matchattr(attr0, k->attr, k->privattr) && matchattr(attr1, k->attr, k->privattr)){ 373fb7f0c93SDavid du Colombier /* check ownership */ 374fb7f0c93SDavid du Colombier if(!matchattr(attr2, k->attr, nil) && !matchattr(attr3, k->attr, nil)) 375fb7f0c93SDavid du Colombier continue; 376260f7b65SDavid du Colombier if(nmatch++ < ki->skip) 3779a747e4fSDavid du Colombier continue; 378260f7b65SDavid du Colombier if(!ki->noconf){ 379260f7b65SDavid du Colombier switch(canusekey(ki->fss, k)){ 3809a747e4fSDavid du Colombier case -1: 3819a747e4fSDavid du Colombier _freeattr(attr1); 3829a747e4fSDavid du Colombier return RpcConfirm; 3839a747e4fSDavid du Colombier case 0: 3849a747e4fSDavid du Colombier continue; 3859a747e4fSDavid du Colombier case 1: 3869a747e4fSDavid du Colombier break; 3879a747e4fSDavid du Colombier } 3889a747e4fSDavid du Colombier } 3899a747e4fSDavid du Colombier _freeattr(attr1); 3904de34a7eSDavid du Colombier _freeattr(attr2); 3914de34a7eSDavid du Colombier _freeattr(attr3); 3929a747e4fSDavid du Colombier k->ref++; 3939a747e4fSDavid du Colombier *ret = k; 3949a747e4fSDavid du Colombier return RpcOk; 3959a747e4fSDavid du Colombier } 3969a747e4fSDavid du Colombier } 397260f7b65SDavid du Colombier flog("%d: no key matches %A %A %A %A", ki->fss->seqnum, attr0, attr1, attr2, attr3); 3989a747e4fSDavid du Colombier werrstr("no key matches %A %A", attr0, attr1); 3994de34a7eSDavid du Colombier _freeattr(attr2); 4004de34a7eSDavid du Colombier _freeattr(attr3); 4019a747e4fSDavid du Colombier s = RpcFailure; 402fb7f0c93SDavid du Colombier if(askforkeys && who==nil && (hasqueries(attr0) || hasqueries(attr1))){ 4039a747e4fSDavid du Colombier if(nmatch == 0){ 4049a747e4fSDavid du Colombier attr0 = _copyattr(attr0); 4059a747e4fSDavid du Colombier for(l=&attr0; *l; l=&(*l)->next) 4069a747e4fSDavid du Colombier ; 4079a747e4fSDavid du Colombier *l = attr1; 4089a747e4fSDavid du Colombier for(l=&attr0; *l; ){ 4092ebbfa15SDavid du Colombier if(ignoreattr((*l)->name)){ 4109a747e4fSDavid du Colombier a = *l; 4119a747e4fSDavid du Colombier *l = (*l)->next; 4129a747e4fSDavid du Colombier a->next = nil; 4139a747e4fSDavid du Colombier _freeattr(a); 4149a747e4fSDavid du Colombier }else 4159a747e4fSDavid du Colombier l = &(*l)->next; 4169a747e4fSDavid du Colombier } 4179a747e4fSDavid du Colombier attr0 = sortattr(attr0); 418260f7b65SDavid du Colombier snprint(ki->fss->keyinfo, sizeof ki->fss->keyinfo, "%A", attr0); 4199a747e4fSDavid du Colombier _freeattr(attr0); 4209a747e4fSDavid du Colombier attr1 = nil; /* attr1 was linked to attr0 */ 4219a747e4fSDavid du Colombier }else 422260f7b65SDavid du Colombier ki->fss->keyinfo[0] = '\0'; 4239a747e4fSDavid du Colombier s = RpcNeedkey; 4249a747e4fSDavid du Colombier } 4259a747e4fSDavid du Colombier _freeattr(attr1); 4269a747e4fSDavid du Colombier if(s == RpcFailure) 427260f7b65SDavid du Colombier return failure(ki->fss, nil); /* loads error string */ 4289a747e4fSDavid du Colombier return s; 4299a747e4fSDavid du Colombier } 4309a747e4fSDavid du Colombier 4319a747e4fSDavid du Colombier int 4329a747e4fSDavid du Colombier findp9authkey(Key **k, Fsstate *fss) 4339a747e4fSDavid du Colombier { 4349a747e4fSDavid du Colombier char *dom; 435260f7b65SDavid du Colombier Keyinfo ki; 4369a747e4fSDavid du Colombier 4379a747e4fSDavid du Colombier /* 4389a747e4fSDavid du Colombier * We don't use fss->attr here because we don't 4399a747e4fSDavid du Colombier * care about what the user name is set to, for instance. 4409a747e4fSDavid du Colombier */ 441260f7b65SDavid du Colombier mkkeyinfo(&ki, fss, nil); 442260f7b65SDavid du Colombier ki.attr = nil; 443260f7b65SDavid du Colombier ki.user = nil; 4442ebbfa15SDavid du Colombier if(dom = _strfindattr(fss->attr, "dom")) 445260f7b65SDavid du Colombier return findkey(k, &ki, "proto=p9sk1 dom=%q role=server user?", dom); 4469a747e4fSDavid du Colombier else 447260f7b65SDavid du Colombier return findkey(k, &ki, "proto=p9sk1 role=server dom? user?"); 4489a747e4fSDavid du Colombier } 4499a747e4fSDavid du Colombier 4509a747e4fSDavid du Colombier Proto* 4519a747e4fSDavid du Colombier findproto(char *name) 4529a747e4fSDavid du Colombier { 4539a747e4fSDavid du Colombier int i; 4549a747e4fSDavid du Colombier 4559a747e4fSDavid du Colombier for(i=0; prototab[i]; i++) 4569a747e4fSDavid du Colombier if(strcmp(name, prototab[i]->name) == 0) 4579a747e4fSDavid du Colombier return prototab[i]; 4589a747e4fSDavid du Colombier return nil; 4599a747e4fSDavid du Colombier } 4609a747e4fSDavid du Colombier 4619a747e4fSDavid du Colombier char* 4629a747e4fSDavid du Colombier getnvramkey(int flag, char **secstorepw) 4639a747e4fSDavid du Colombier { 4649a747e4fSDavid du Colombier char *s; 4659a747e4fSDavid du Colombier Nvrsafe safe; 4669a747e4fSDavid du Colombier char spw[CONFIGLEN+1]; 4679a747e4fSDavid du Colombier int i; 4689a747e4fSDavid du Colombier 4699a747e4fSDavid du Colombier memset(&safe, 0, sizeof safe); 4709a747e4fSDavid du Colombier /* 4719a747e4fSDavid du Colombier * readnvram can return -1 meaning nvram wasn't written, 4729a747e4fSDavid du Colombier * but safe still holds good data. 4739a747e4fSDavid du Colombier */ 4745fe11e25SDavid du Colombier if(readnvram(&safe, flag)<0 && safe.authid[0]==0) 4759a747e4fSDavid du Colombier return nil; 4769a747e4fSDavid du Colombier 4779a747e4fSDavid du Colombier /* 4789a747e4fSDavid du Colombier * we're using the config area to hold the secstore 4799a747e4fSDavid du Colombier * password. if there's anything there, return it. 4809a747e4fSDavid du Colombier */ 4819a747e4fSDavid du Colombier memmove(spw, safe.config, CONFIGLEN); 4829a747e4fSDavid du Colombier spw[CONFIGLEN] = 0; 4839a747e4fSDavid du Colombier if(spw[0] != 0) 4849a747e4fSDavid du Colombier *secstorepw = estrdup(spw); 4859a747e4fSDavid du Colombier 4869a747e4fSDavid du Colombier /* 4879a747e4fSDavid du Colombier * only use nvram key if it is non-zero 4889a747e4fSDavid du Colombier */ 4899a747e4fSDavid du Colombier for(i = 0; i < DESKEYLEN; i++) 4909a747e4fSDavid du Colombier if(safe.machkey[i] != 0) 4919a747e4fSDavid du Colombier break; 4929a747e4fSDavid du Colombier if(i == DESKEYLEN) 4939a747e4fSDavid du Colombier return nil; 4949a747e4fSDavid du Colombier 4959a747e4fSDavid du Colombier s = emalloc(512); 4969a747e4fSDavid du Colombier fmtinstall('H', encodefmt); 4979a747e4fSDavid du Colombier sprint(s, "key proto=p9sk1 user=%q dom=%q !hex=%.*H !password=______", 4989a747e4fSDavid du Colombier safe.authid, safe.authdom, DESKEYLEN, safe.machkey); 4999a747e4fSDavid du Colombier writehostowner(safe.authid); 5009a747e4fSDavid du Colombier 5019a747e4fSDavid du Colombier return s; 5029a747e4fSDavid du Colombier } 5039a747e4fSDavid du Colombier 5049a747e4fSDavid du Colombier int 5059a747e4fSDavid du Colombier isclient(char *role) 5069a747e4fSDavid du Colombier { 5079a747e4fSDavid du Colombier if(role == nil){ 5089a747e4fSDavid du Colombier werrstr("role not specified"); 5099a747e4fSDavid du Colombier return -1; 5109a747e4fSDavid du Colombier } 5119a747e4fSDavid du Colombier if(strcmp(role, "server") == 0) 5129a747e4fSDavid du Colombier return 0; 5139a747e4fSDavid du Colombier if(strcmp(role, "client") == 0) 5149a747e4fSDavid du Colombier return 1; 5159a747e4fSDavid du Colombier werrstr("unknown role %q", role); 5169a747e4fSDavid du Colombier return -1; 5179a747e4fSDavid du Colombier } 5189a747e4fSDavid du Colombier 5199a747e4fSDavid du Colombier static int 5209a747e4fSDavid du Colombier hasname(Attr *a0, Attr *a1, char *name) 5219a747e4fSDavid du Colombier { 5229a747e4fSDavid du Colombier return _findattr(a0, name) || _findattr(a1, name); 5239a747e4fSDavid du Colombier } 5249a747e4fSDavid du Colombier 5259a747e4fSDavid du Colombier static int 5269a747e4fSDavid du Colombier hasnameval(Attr *a0, Attr *a1, char *name, char *val) 5279a747e4fSDavid du Colombier { 5289a747e4fSDavid du Colombier Attr *a; 5299a747e4fSDavid du Colombier 5309a747e4fSDavid du Colombier for(a=_findattr(a0, name); a; a=_findattr(a->next, name)) 5312ebbfa15SDavid du Colombier if(strcmp(a->val, val) == 0) 5329a747e4fSDavid du Colombier return 1; 5339a747e4fSDavid du Colombier for(a=_findattr(a1, name); a; a=_findattr(a->next, name)) 5342ebbfa15SDavid du Colombier if(strcmp(a->val, val) == 0) 5359a747e4fSDavid du Colombier return 1; 5369a747e4fSDavid du Colombier return 0; 5379a747e4fSDavid du Colombier } 5389a747e4fSDavid du Colombier 5399a747e4fSDavid du Colombier int 5409a747e4fSDavid du Colombier matchattr(Attr *pat, Attr *a0, Attr *a1) 5419a747e4fSDavid du Colombier { 5429a747e4fSDavid du Colombier int type; 5439a747e4fSDavid du Colombier 5449a747e4fSDavid du Colombier for(; pat; pat=pat->next){ 5459a747e4fSDavid du Colombier type = pat->type; 5462ebbfa15SDavid du Colombier if(ignoreattr(pat->name)) 5479a747e4fSDavid du Colombier type = AttrDefault; 5489a747e4fSDavid du Colombier switch(type){ 5499a747e4fSDavid du Colombier case AttrQuery: /* name=something be present */ 5502ebbfa15SDavid du Colombier if(!hasname(a0, a1, pat->name)) 5519a747e4fSDavid du Colombier return 0; 5529a747e4fSDavid du Colombier break; 5539a747e4fSDavid du Colombier case AttrNameval: /* name=val must be present */ 5542ebbfa15SDavid du Colombier if(!hasnameval(a0, a1, pat->name, pat->val)) 5559a747e4fSDavid du Colombier return 0; 5569a747e4fSDavid du Colombier break; 5579a747e4fSDavid du Colombier case AttrDefault: /* name=val must be present if name=anything is present */ 5582ebbfa15SDavid du Colombier if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val)) 5599a747e4fSDavid du Colombier return 0; 5609a747e4fSDavid du Colombier break; 5619a747e4fSDavid du Colombier } 5629a747e4fSDavid du Colombier } 5639a747e4fSDavid du Colombier return 1; 5649a747e4fSDavid du Colombier } 5659a747e4fSDavid du Colombier 5669a747e4fSDavid du Colombier void 5679a747e4fSDavid du Colombier memrandom(void *p, int n) 5689a747e4fSDavid du Colombier { 5699a747e4fSDavid du Colombier uchar *cp; 5709a747e4fSDavid du Colombier 5719a747e4fSDavid du Colombier for(cp = (uchar*)p; n > 0; n--) 5729a747e4fSDavid du Colombier *cp++ = fastrand(); 5739a747e4fSDavid du Colombier } 5749a747e4fSDavid du Colombier 5759a747e4fSDavid du Colombier /* 5763ff48bf5SDavid du Colombier * keep caphash fd open since opens of it could be disabled 5773ff48bf5SDavid du Colombier */ 5783ff48bf5SDavid du Colombier static int caphashfd; 5793ff48bf5SDavid du Colombier 5803ff48bf5SDavid du Colombier void 5813ff48bf5SDavid du Colombier initcap(void) 5823ff48bf5SDavid du Colombier { 5833ff48bf5SDavid du Colombier caphashfd = open("#¤/caphash", OWRITE); 584d9306527SDavid du Colombier // if(caphashfd < 0) 585d9306527SDavid du Colombier // fprint(2, "%s: opening #¤/caphash: %r\n", argv0); 5863ff48bf5SDavid du Colombier } 5873ff48bf5SDavid du Colombier 5883ff48bf5SDavid du Colombier /* 5899a747e4fSDavid du Colombier * create a change uid capability 5909a747e4fSDavid du Colombier */ 5919a747e4fSDavid du Colombier char* 5923ff48bf5SDavid du Colombier mkcap(char *from, char *to) 5939a747e4fSDavid du Colombier { 5949a747e4fSDavid du Colombier uchar rand[20]; 5959a747e4fSDavid du Colombier char *cap; 5969a747e4fSDavid du Colombier char *key; 5973ff48bf5SDavid du Colombier int nfrom, nto; 5989a747e4fSDavid du Colombier uchar hash[SHA1dlen]; 5999a747e4fSDavid du Colombier 6003ff48bf5SDavid du Colombier if(caphashfd < 0) 6019a747e4fSDavid du Colombier return nil; 6029a747e4fSDavid du Colombier 6039a747e4fSDavid du Colombier /* create the capability */ 6043ff48bf5SDavid du Colombier nto = strlen(to); 6053ff48bf5SDavid du Colombier nfrom = strlen(from); 6063ff48bf5SDavid du Colombier cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1); 6073ff48bf5SDavid du Colombier sprint(cap, "%s@%s", from, to); 6089a747e4fSDavid du Colombier memrandom(rand, sizeof(rand)); 6093ff48bf5SDavid du Colombier key = cap+nfrom+1+nto+1; 6109a747e4fSDavid du Colombier enc64(key, sizeof(rand)*3, rand, sizeof(rand)); 6119a747e4fSDavid du Colombier 6129a747e4fSDavid du Colombier /* hash the capability */ 6133ff48bf5SDavid du Colombier hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil); 6149a747e4fSDavid du Colombier 6159a747e4fSDavid du Colombier /* give the kernel the hash */ 6163ff48bf5SDavid du Colombier key[-1] = '@'; 6173ff48bf5SDavid du Colombier if(write(caphashfd, hash, SHA1dlen) < 0){ 6189a747e4fSDavid du Colombier free(cap); 6199a747e4fSDavid du Colombier return nil; 6209a747e4fSDavid du Colombier } 6219a747e4fSDavid du Colombier 6229a747e4fSDavid du Colombier return cap; 6239a747e4fSDavid du Colombier } 6249a747e4fSDavid du Colombier 6259a747e4fSDavid du Colombier int 6269a747e4fSDavid du Colombier phaseerror(Fsstate *s, char *op) 6279a747e4fSDavid du Colombier { 6289a747e4fSDavid du Colombier char tmp[32]; 6299a747e4fSDavid du Colombier 6309a747e4fSDavid du Colombier werrstr("protocol phase error: %s in state %s", op, phasename(s, s->phase, tmp)); 6319a747e4fSDavid du Colombier return RpcPhase; 6329a747e4fSDavid du Colombier } 6339a747e4fSDavid du Colombier 6349a747e4fSDavid du Colombier char* 6359a747e4fSDavid du Colombier phasename(Fsstate *fss, int phase, char *tmp) 6369a747e4fSDavid du Colombier { 6379a747e4fSDavid du Colombier char *name; 6389a747e4fSDavid du Colombier 6399a747e4fSDavid du Colombier if(fss->phase == Broken) 6409a747e4fSDavid du Colombier name = "Broken"; 6419a747e4fSDavid du Colombier else if(phase == Established) 6429a747e4fSDavid du Colombier name = "Established"; 6439a747e4fSDavid du Colombier else if(phase == Notstarted) 6449a747e4fSDavid du Colombier name = "Notstarted"; 6459a747e4fSDavid du Colombier else if(phase < 0 || phase >= fss->maxphase 6469a747e4fSDavid du Colombier || (name = fss->phasename[phase]) == nil){ 6479a747e4fSDavid du Colombier sprint(tmp, "%d", phase); 6489a747e4fSDavid du Colombier name = tmp; 6499a747e4fSDavid du Colombier } 6509a747e4fSDavid du Colombier return name; 6519a747e4fSDavid du Colombier } 6529a747e4fSDavid du Colombier 6539a747e4fSDavid du Colombier static int 6549a747e4fSDavid du Colombier outin(char *prompt, char *def, int len) 6559a747e4fSDavid du Colombier { 6562ebbfa15SDavid du Colombier char *s; 6579a747e4fSDavid du Colombier 6589a747e4fSDavid du Colombier s = readcons(prompt, def, 0); 6599a747e4fSDavid du Colombier if(s == nil) 6609a747e4fSDavid du Colombier return -1; 6612ebbfa15SDavid du Colombier if(s == nil) 6622ebbfa15SDavid du Colombier sysfatal("s==nil???"); 6632ebbfa15SDavid du Colombier strncpy(def, s, len); 6649a747e4fSDavid du Colombier def[len-1] = 0; 6652ebbfa15SDavid du Colombier free(s); 6669a747e4fSDavid du Colombier return strlen(def); 6679a747e4fSDavid du Colombier } 6689a747e4fSDavid du Colombier 6699a747e4fSDavid du Colombier /* 6709a747e4fSDavid du Colombier * get host owner and set it 6719a747e4fSDavid du Colombier */ 6729a747e4fSDavid du Colombier void 6739a747e4fSDavid du Colombier promptforhostowner(void) 6749a747e4fSDavid du Colombier { 6759a747e4fSDavid du Colombier char owner[64], *p; 6769a747e4fSDavid du Colombier 6779a747e4fSDavid du Colombier /* hack for bitsy; can't prompt during boot */ 6789a747e4fSDavid du Colombier if(p = getenv("user")){ 6799a747e4fSDavid du Colombier writehostowner(p); 680d9306527SDavid du Colombier free(p); 6819a747e4fSDavid du Colombier return; 6829a747e4fSDavid du Colombier } 683d9306527SDavid du Colombier free(p); 6849a747e4fSDavid du Colombier 6859a747e4fSDavid du Colombier strcpy(owner, "none"); 6869a747e4fSDavid du Colombier do{ 6879a747e4fSDavid du Colombier outin("user", owner, sizeof(owner)); 6889a747e4fSDavid du Colombier } while(*owner == 0); 6899a747e4fSDavid du Colombier writehostowner(owner); 6909a747e4fSDavid du Colombier } 6919a747e4fSDavid du Colombier 6922ebbfa15SDavid du Colombier char* 6932ebbfa15SDavid du Colombier estrappend(char *s, char *fmt, ...) 6942ebbfa15SDavid du Colombier { 6952ebbfa15SDavid du Colombier char *t; 6962ebbfa15SDavid du Colombier va_list arg; 6972ebbfa15SDavid du Colombier 6982ebbfa15SDavid du Colombier va_start(arg, fmt); 6992ebbfa15SDavid du Colombier t = vsmprint(fmt, arg); 7002ebbfa15SDavid du Colombier if(t == nil) 7012ebbfa15SDavid du Colombier sysfatal("out of memory"); 7022ebbfa15SDavid du Colombier va_end(arg); 7032ebbfa15SDavid du Colombier s = erealloc(s, strlen(s)+strlen(t)+1); 7042ebbfa15SDavid du Colombier strcat(s, t); 7052ebbfa15SDavid du Colombier free(t); 7062ebbfa15SDavid du Colombier return s; 7072ebbfa15SDavid du Colombier } 7082ebbfa15SDavid du Colombier 7092ebbfa15SDavid du Colombier 7109a747e4fSDavid du Colombier /* 7119a747e4fSDavid du Colombier * prompt for a string with a possible default response 7129a747e4fSDavid du Colombier */ 7132ebbfa15SDavid du Colombier char* 7149a747e4fSDavid du Colombier readcons(char *prompt, char *def, int raw) 7159a747e4fSDavid du Colombier { 7169a747e4fSDavid du Colombier int fdin, fdout, ctl, n; 7179a747e4fSDavid du Colombier char line[10]; 7182ebbfa15SDavid du Colombier char *s; 7199a747e4fSDavid du Colombier 7209a747e4fSDavid du Colombier fdin = open("/dev/cons", OREAD); 7219a747e4fSDavid du Colombier if(fdin < 0) 7229a747e4fSDavid du Colombier fdin = 0; 7239a747e4fSDavid du Colombier fdout = open("/dev/cons", OWRITE); 7249a747e4fSDavid du Colombier if(fdout < 0) 7259a747e4fSDavid du Colombier fdout = 1; 7269a747e4fSDavid du Colombier if(def != nil) 7279a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 7289a747e4fSDavid du Colombier else 7299a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 7309a747e4fSDavid du Colombier if(raw){ 7319a747e4fSDavid du Colombier ctl = open("/dev/consctl", OWRITE); 7329a747e4fSDavid du Colombier if(ctl >= 0) 7339a747e4fSDavid du Colombier write(ctl, "rawon", 5); 7349a747e4fSDavid du Colombier } else 7359a747e4fSDavid du Colombier ctl = -1; 7362ebbfa15SDavid du Colombier s = estrdup(""); 7379a747e4fSDavid du Colombier for(;;){ 7389a747e4fSDavid du Colombier n = read(fdin, line, 1); 7399a747e4fSDavid du Colombier if(n == 0){ 7409a747e4fSDavid du Colombier Error: 7419a747e4fSDavid du Colombier close(fdin); 7429a747e4fSDavid du Colombier close(fdout); 7439a747e4fSDavid du Colombier if(ctl >= 0) 7449a747e4fSDavid du Colombier close(ctl); 7452ebbfa15SDavid du Colombier free(s); 7469a747e4fSDavid du Colombier return nil; 7479a747e4fSDavid du Colombier } 7489a747e4fSDavid du Colombier if(n < 0) 7499a747e4fSDavid du Colombier goto Error; 7509a747e4fSDavid du Colombier if(line[0] == 0x7f) 7519a747e4fSDavid du Colombier goto Error; 7529a747e4fSDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){ 7539a747e4fSDavid du Colombier if(raw){ 7549a747e4fSDavid du Colombier write(ctl, "rawoff", 6); 7559a747e4fSDavid du Colombier write(fdout, "\n", 1); 7569a747e4fSDavid du Colombier } 7579a747e4fSDavid du Colombier close(ctl); 7589a747e4fSDavid du Colombier close(fdin); 7599a747e4fSDavid du Colombier close(fdout); 7602ebbfa15SDavid du Colombier if(*s == 0 && def != nil) 7612ebbfa15SDavid du Colombier s = estrappend(s, "%s", def); 7629a747e4fSDavid du Colombier return s; 7639a747e4fSDavid du Colombier } 7649a747e4fSDavid du Colombier if(line[0] == '\b'){ 7652ebbfa15SDavid du Colombier if(strlen(s) > 0) 7662ebbfa15SDavid du Colombier s[strlen(s)-1] = 0; 7679a747e4fSDavid du Colombier } else if(line[0] == 0x15) { /* ^U: line kill */ 7682ebbfa15SDavid du Colombier if(def != nil) 7692ebbfa15SDavid du Colombier fprint(fdout, "\n%s[%s]: ", prompt, def); 7702ebbfa15SDavid du Colombier else 7712ebbfa15SDavid du Colombier fprint(fdout, "\n%s: ", prompt); 7722ebbfa15SDavid du Colombier 7732ebbfa15SDavid du Colombier s[0] = 0; 7749a747e4fSDavid du Colombier } else { 7752ebbfa15SDavid du Colombier s = estrappend(s, "%c", line[0]); 7769a747e4fSDavid du Colombier } 7779a747e4fSDavid du Colombier } 7789a747e4fSDavid du Colombier } 7799a747e4fSDavid du Colombier 7809a747e4fSDavid du Colombier /* 7819a747e4fSDavid du Colombier * Insert a key into the keyring. 7829a747e4fSDavid du Colombier * If the public attributes are identical to some other key, replace that one. 7839a747e4fSDavid du Colombier */ 7849a747e4fSDavid du Colombier int 78570b8e010SDavid du Colombier replacekey(Key *kn, int before) 7869a747e4fSDavid du Colombier { 7879a747e4fSDavid du Colombier int i; 7889a747e4fSDavid du Colombier Key *k; 7899a747e4fSDavid du Colombier 7909a747e4fSDavid du Colombier for(i=0; i<ring->nkey; i++){ 7919a747e4fSDavid du Colombier k = ring->key[i]; 7929a747e4fSDavid du Colombier if(matchattr(kn->attr, k->attr, nil) && matchattr(k->attr, kn->attr, nil)){ 7939a747e4fSDavid du Colombier closekey(k); 7949a747e4fSDavid du Colombier kn->ref++; 7959a747e4fSDavid du Colombier ring->key[i] = kn; 7969a747e4fSDavid du Colombier return 0; 7979a747e4fSDavid du Colombier } 7989a747e4fSDavid du Colombier } 7999a747e4fSDavid du Colombier if(ring->nkey%16 == 0) 8009a747e4fSDavid du Colombier ring->key = erealloc(ring->key, (ring->nkey+16)*sizeof(ring->key[0])); 8019a747e4fSDavid du Colombier kn->ref++; 80270b8e010SDavid du Colombier if(before){ 80370b8e010SDavid du Colombier memmove(ring->key+1, ring->key, ring->nkey*sizeof ring->key[0]); 80470b8e010SDavid du Colombier ring->key[0] = kn; 80570b8e010SDavid du Colombier ring->nkey++; 80670b8e010SDavid du Colombier }else 8079a747e4fSDavid du Colombier ring->key[ring->nkey++] = kn; 8089a747e4fSDavid du Colombier return 0; 8099a747e4fSDavid du Colombier } 8109a747e4fSDavid du Colombier 8119a747e4fSDavid du Colombier char* 8129a747e4fSDavid du Colombier safecpy(char *to, char *from, int n) 8139a747e4fSDavid du Colombier { 8149a747e4fSDavid du Colombier memset(to, 0, n); 8159a747e4fSDavid du Colombier if(n == 1) 8169a747e4fSDavid du Colombier return to; 8179a747e4fSDavid du Colombier if(from==nil) 81874f16c81SDavid du Colombier sysfatal("safecpy called with from==nil, pc=%#p\n", 8199a747e4fSDavid du Colombier getcallerpc(&to)); 8209a747e4fSDavid du Colombier strncpy(to, from, n-1); 8219a747e4fSDavid du Colombier return to; 8229a747e4fSDavid du Colombier } 8239a747e4fSDavid du Colombier 8249a747e4fSDavid du Colombier Attr* 8259a747e4fSDavid du Colombier setattr(Attr *a, char *fmt, ...) 8269a747e4fSDavid du Colombier { 8279a747e4fSDavid du Colombier char buf[1024]; 8289a747e4fSDavid du Colombier va_list arg; 8299a747e4fSDavid du Colombier Attr *b; 8309a747e4fSDavid du Colombier 8319a747e4fSDavid du Colombier va_start(arg, fmt); 8329a747e4fSDavid du Colombier vseprint(buf, buf+sizeof buf, fmt, arg); 8339a747e4fSDavid du Colombier va_end(arg); 8349a747e4fSDavid du Colombier b = _parseattr(buf); 8359a747e4fSDavid du Colombier a = setattrs(a, b); 8369a747e4fSDavid du Colombier setmalloctag(a, getcallerpc(&a)); 8379a747e4fSDavid du Colombier _freeattr(b); 8389a747e4fSDavid du Colombier return a; 8399a747e4fSDavid du Colombier } 8409a747e4fSDavid du Colombier 8419a747e4fSDavid du Colombier /* 8429a747e4fSDavid du Colombier * add attributes in list b to list a. If any attributes are in 8439a747e4fSDavid du Colombier * both lists, replace those in a by those in b. 8449a747e4fSDavid du Colombier */ 8459a747e4fSDavid du Colombier Attr* 8469a747e4fSDavid du Colombier setattrs(Attr *a, Attr *b) 8479a747e4fSDavid du Colombier { 8489a747e4fSDavid du Colombier int found; 8499a747e4fSDavid du Colombier Attr **l, *freea; 8509a747e4fSDavid du Colombier 8519a747e4fSDavid du Colombier for(; b; b=b->next){ 8529a747e4fSDavid du Colombier found = 0; 8539a747e4fSDavid du Colombier for(l=&a; *l; ){ 8542ebbfa15SDavid du Colombier if(strcmp(b->name, (*l)->name) == 0){ 8559a747e4fSDavid du Colombier switch(b->type){ 8569a747e4fSDavid du Colombier case AttrNameval: 8579a747e4fSDavid du Colombier if(!found){ 8589a747e4fSDavid du Colombier found = 1; 8592ebbfa15SDavid du Colombier free((*l)->val); 8602ebbfa15SDavid du Colombier (*l)->val = estrdup(b->val); 8619a747e4fSDavid du Colombier (*l)->type = AttrNameval; 8629a747e4fSDavid du Colombier l = &(*l)->next; 8639a747e4fSDavid du Colombier }else{ 8649a747e4fSDavid du Colombier freea = *l; 8659a747e4fSDavid du Colombier *l = (*l)->next; 8669a747e4fSDavid du Colombier freea->next = nil; 8679a747e4fSDavid du Colombier _freeattr(freea); 8689a747e4fSDavid du Colombier } 8699a747e4fSDavid du Colombier break; 8709a747e4fSDavid du Colombier case AttrQuery: 871f0ed0fb6SDavid du Colombier goto continue2; 8729a747e4fSDavid du Colombier } 8739a747e4fSDavid du Colombier }else 8749a747e4fSDavid du Colombier l = &(*l)->next; 8759a747e4fSDavid du Colombier } 8769a747e4fSDavid du Colombier if(found == 0){ 8772ebbfa15SDavid du Colombier *l = _mkattr(b->type, b->name, b->val, nil); 8789a747e4fSDavid du Colombier setmalloctag(*l, getcallerpc(&a)); 8799a747e4fSDavid du Colombier } 880f0ed0fb6SDavid du Colombier continue2:; 8819a747e4fSDavid du Colombier } 8829a747e4fSDavid du Colombier return a; 8839a747e4fSDavid du Colombier } 8849a747e4fSDavid du Colombier 8859a747e4fSDavid du Colombier void 8869a747e4fSDavid du Colombier setmalloctaghere(void *v) 8879a747e4fSDavid du Colombier { 8889a747e4fSDavid du Colombier setmalloctag(v, getcallerpc(&v)); 8899a747e4fSDavid du Colombier } 8909a747e4fSDavid du Colombier 8919a747e4fSDavid du Colombier Attr* 8929a747e4fSDavid du Colombier sortattr(Attr *a) 8939a747e4fSDavid du Colombier { 8949a747e4fSDavid du Colombier int i; 8959a747e4fSDavid du Colombier Attr *anext, *a0, *a1, **l; 8969a747e4fSDavid du Colombier 8979a747e4fSDavid du Colombier if(a == nil || a->next == nil) 8989a747e4fSDavid du Colombier return a; 8999a747e4fSDavid du Colombier 9009a747e4fSDavid du Colombier /* cut list in halves */ 9019a747e4fSDavid du Colombier a0 = nil; 9029a747e4fSDavid du Colombier a1 = nil; 9039a747e4fSDavid du Colombier i = 0; 9049a747e4fSDavid du Colombier for(; a; a=anext){ 9059a747e4fSDavid du Colombier anext = a->next; 9069a747e4fSDavid du Colombier if(i++%2){ 9079a747e4fSDavid du Colombier a->next = a0; 9089a747e4fSDavid du Colombier a0 = a; 9099a747e4fSDavid du Colombier }else{ 9109a747e4fSDavid du Colombier a->next = a1; 9119a747e4fSDavid du Colombier a1 = a; 9129a747e4fSDavid du Colombier } 9139a747e4fSDavid du Colombier } 9149a747e4fSDavid du Colombier 9159a747e4fSDavid du Colombier /* sort */ 9169a747e4fSDavid du Colombier a0 = sortattr(a0); 9179a747e4fSDavid du Colombier a1 = sortattr(a1); 9189a747e4fSDavid du Colombier 9199a747e4fSDavid du Colombier /* merge */ 9209a747e4fSDavid du Colombier l = &a; 9219a747e4fSDavid du Colombier while(a0 || a1){ 9229a747e4fSDavid du Colombier if(a1==nil){ 9239a747e4fSDavid du Colombier anext = a0; 9249a747e4fSDavid du Colombier a0 = a0->next; 9259a747e4fSDavid du Colombier }else if(a0==nil){ 9269a747e4fSDavid du Colombier anext = a1; 9279a747e4fSDavid du Colombier a1 = a1->next; 9282ebbfa15SDavid du Colombier }else if(strcmp(a0->name, a1->name) < 0){ 9299a747e4fSDavid du Colombier anext = a0; 9309a747e4fSDavid du Colombier a0 = a0->next; 9319a747e4fSDavid du Colombier }else{ 9329a747e4fSDavid du Colombier anext = a1; 9339a747e4fSDavid du Colombier a1 = a1->next; 9349a747e4fSDavid du Colombier } 9359a747e4fSDavid du Colombier *l = anext; 9369a747e4fSDavid du Colombier l = &(*l)->next; 9379a747e4fSDavid du Colombier } 9389a747e4fSDavid du Colombier *l = nil; 9399a747e4fSDavid du Colombier return a; 9409a747e4fSDavid du Colombier } 9419a747e4fSDavid du Colombier 9429a747e4fSDavid du Colombier int 9439a747e4fSDavid du Colombier toosmall(Fsstate *fss, uint n) 9449a747e4fSDavid du Colombier { 9459a747e4fSDavid du Colombier fss->rpc.nwant = n; 9469a747e4fSDavid du Colombier return RpcToosmall; 9479a747e4fSDavid du Colombier } 9489a747e4fSDavid du Colombier 9499a747e4fSDavid du Colombier void 9509a747e4fSDavid du Colombier writehostowner(char *owner) 9519a747e4fSDavid du Colombier { 9529a747e4fSDavid du Colombier int fd; 9539a747e4fSDavid du Colombier char *s; 9549a747e4fSDavid du Colombier 9559a747e4fSDavid du Colombier if((s = strchr(owner,'@')) != nil){ 9569a747e4fSDavid du Colombier *s++ = 0; 9579a747e4fSDavid du Colombier strncpy(secstore, s, (sizeof secstore)-1); 9589a747e4fSDavid du Colombier } 9599a747e4fSDavid du Colombier fd = open("#c/hostowner", OWRITE); 9609a747e4fSDavid du Colombier if(fd >= 0){ 9619a747e4fSDavid du Colombier if(fprint(fd, "%s", owner) < 0) 962d854de59SDavid du Colombier fprint(2, "factotum: setting #c/hostowner to %q: %r\n", 963d854de59SDavid du Colombier owner); 9649a747e4fSDavid du Colombier close(fd); 9659a747e4fSDavid du Colombier } 9669a747e4fSDavid du Colombier } 9679a747e4fSDavid du Colombier 9685d459b5aSDavid du Colombier int 9695d459b5aSDavid du Colombier attrnamefmt(Fmt *fmt) 9705d459b5aSDavid du Colombier { 9715d459b5aSDavid du Colombier char *b, buf[1024], *ebuf; 9725d459b5aSDavid du Colombier Attr *a; 9735d459b5aSDavid du Colombier 9745d459b5aSDavid du Colombier ebuf = buf+sizeof buf; 9755d459b5aSDavid du Colombier b = buf; 9765d459b5aSDavid du Colombier strcpy(buf, " "); 9775d459b5aSDavid du Colombier for(a=va_arg(fmt->args, Attr*); a; a=a->next){ 9785d459b5aSDavid du Colombier if(a->name == nil) 9795d459b5aSDavid du Colombier continue; 9802ebbfa15SDavid du Colombier b = seprint(b, ebuf, " %q?", a->name); 9815d459b5aSDavid du Colombier } 9825d459b5aSDavid du Colombier return fmtstrcpy(fmt, buf+1); 9835d459b5aSDavid du Colombier } 984260f7b65SDavid du Colombier 985260f7b65SDavid du Colombier void 986260f7b65SDavid du Colombier disablekey(Key *k) 987260f7b65SDavid du Colombier { 988260f7b65SDavid du Colombier Attr *a; 989260f7b65SDavid du Colombier 990b05f4f54SDavid du Colombier if(sflag) /* not on servers */ 991b05f4f54SDavid du Colombier return; 992260f7b65SDavid du Colombier for(a=k->attr; a; a=a->next){ 993260f7b65SDavid du Colombier if(a->type==AttrNameval && strcmp(a->name, "disabled") == 0) 994260f7b65SDavid du Colombier return; 995260f7b65SDavid du Colombier if(a->next == nil) 996260f7b65SDavid du Colombier break; 997260f7b65SDavid du Colombier } 998260f7b65SDavid du Colombier if(a) 999260f7b65SDavid du Colombier a->next = _mkattr(AttrNameval, "disabled", "by.factotum", nil); 1000260f7b65SDavid du Colombier else 1001260f7b65SDavid du Colombier k->attr = _mkattr(AttrNameval, "disabled", "by.factotum", nil); /* not reached: always a proto attribute */ 1002260f7b65SDavid du Colombier } 1003