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
bindnetcs(void)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
_authdial(char * net,char * authdom)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
478c41de82SDavid du Colombier /* use the auth server passed to us as an arg */
489a747e4fSDavid du Colombier if(authaddr == nil)
499a747e4fSDavid du Colombier return -1;
508c41de82SDavid du Colombier fd = dial(netmkaddr(authaddr, "tcp", "567"), 0, 0, 0);
519a747e4fSDavid du Colombier if(fd >= 0)
529a747e4fSDavid du Colombier return fd;
538c41de82SDavid du Colombier return dial(netmkaddr(authaddr, "il", "566"), 0, 0, 0);
549a747e4fSDavid du Colombier }
559a747e4fSDavid du Colombier
569a747e4fSDavid du Colombier int
secdial(void)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*
promptforkey(char * params)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
sendkey(Attr * attr)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
askuser(char * params)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
canusekey(Fsstate * fss,Key * k)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
closekey(Key * k)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*
pstring(uchar * p,uchar * e,char * s)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*
pcarray(uchar * p,uchar * e,uchar * s,uint n)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*
convAI2M(AuthInfo * ai,uchar * p,int n)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
failure(Fsstate * s,char * fmt,...)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);
27823e56024SDavid du Colombier vsnprint(e, sizeof e, fmt, arg);
2799a747e4fSDavid du Colombier va_end(arg);
2809a747e4fSDavid du Colombier strecpy(s->err, s->err+sizeof(s->err), e);
28187dfdc75SDavid 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
hasqueries(Attr * a)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
ignoreattr(char * s)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*
mkkeyinfo(Keyinfo * k,Fsstate * fss,Attr * attr)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
findkey(Key ** ret,Keyinfo * ki,char * fmt,...)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
findp9authkey(Key ** k,Fsstate * fss)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*
findproto(char * name)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*
getnvramkey(int flag,char ** secstorepw)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);
497*f54edc78SDavid du Colombier snprint(s, 512, "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
isclient(char * role)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
hasname(Attr * a0,Attr * a1,char * name)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
hasnameval(Attr * a0,Attr * a1,char * name,char * val)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
matchattr(Attr * pat,Attr * a0,Attr * a1)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
memrandom(void * p,int n)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
initcap(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*
mkcap(char * from,char * to)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;
597*f54edc78SDavid du Colombier int nfrom, nto, ncap;
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);
606*f54edc78SDavid du Colombier ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1;
607*f54edc78SDavid du Colombier cap = emalloc(ncap);
608*f54edc78SDavid du Colombier snprint(cap, ncap, "%s@%s", from, to);
6099a747e4fSDavid du Colombier memrandom(rand, sizeof(rand));
6103ff48bf5SDavid du Colombier key = cap+nfrom+1+nto+1;
6119a747e4fSDavid du Colombier enc64(key, sizeof(rand)*3, rand, sizeof(rand));
6129a747e4fSDavid du Colombier
6139a747e4fSDavid du Colombier /* hash the capability */
6143ff48bf5SDavid du Colombier hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil);
6159a747e4fSDavid du Colombier
6169a747e4fSDavid du Colombier /* give the kernel the hash */
6173ff48bf5SDavid du Colombier key[-1] = '@';
6183ff48bf5SDavid du Colombier if(write(caphashfd, hash, SHA1dlen) < 0){
6199a747e4fSDavid du Colombier free(cap);
6209a747e4fSDavid du Colombier return nil;
6219a747e4fSDavid du Colombier }
6229a747e4fSDavid du Colombier
6239a747e4fSDavid du Colombier return cap;
6249a747e4fSDavid du Colombier }
6259a747e4fSDavid du Colombier
6269a747e4fSDavid du Colombier int
phaseerror(Fsstate * s,char * op)6279a747e4fSDavid du Colombier phaseerror(Fsstate *s, char *op)
6289a747e4fSDavid du Colombier {
6299a747e4fSDavid du Colombier char tmp[32];
6309a747e4fSDavid du Colombier
6319a747e4fSDavid du Colombier werrstr("protocol phase error: %s in state %s", op, phasename(s, s->phase, tmp));
6329a747e4fSDavid du Colombier return RpcPhase;
6339a747e4fSDavid du Colombier }
6349a747e4fSDavid du Colombier
6359a747e4fSDavid du Colombier char*
phasename(Fsstate * fss,int phase,char * tmp)6369a747e4fSDavid du Colombier phasename(Fsstate *fss, int phase, char *tmp)
6379a747e4fSDavid du Colombier {
6389a747e4fSDavid du Colombier char *name;
6399a747e4fSDavid du Colombier
6409a747e4fSDavid du Colombier if(fss->phase == Broken)
6419a747e4fSDavid du Colombier name = "Broken";
6429a747e4fSDavid du Colombier else if(phase == Established)
6439a747e4fSDavid du Colombier name = "Established";
6449a747e4fSDavid du Colombier else if(phase == Notstarted)
6459a747e4fSDavid du Colombier name = "Notstarted";
6469a747e4fSDavid du Colombier else if(phase < 0 || phase >= fss->maxphase
6479a747e4fSDavid du Colombier || (name = fss->phasename[phase]) == nil){
6489a747e4fSDavid du Colombier sprint(tmp, "%d", phase);
6499a747e4fSDavid du Colombier name = tmp;
6509a747e4fSDavid du Colombier }
6519a747e4fSDavid du Colombier return name;
6529a747e4fSDavid du Colombier }
6539a747e4fSDavid du Colombier
6549a747e4fSDavid du Colombier static int
outin(char * prompt,char * def,int len)6559a747e4fSDavid du Colombier outin(char *prompt, char *def, int len)
6569a747e4fSDavid du Colombier {
6572ebbfa15SDavid du Colombier char *s;
6589a747e4fSDavid du Colombier
6599a747e4fSDavid du Colombier s = readcons(prompt, def, 0);
6609a747e4fSDavid du Colombier if(s == nil)
6619a747e4fSDavid du Colombier return -1;
6622ebbfa15SDavid du Colombier if(s == nil)
6632ebbfa15SDavid du Colombier sysfatal("s==nil???");
6642ebbfa15SDavid du Colombier strncpy(def, s, len);
6659a747e4fSDavid du Colombier def[len-1] = 0;
6662ebbfa15SDavid du Colombier free(s);
6679a747e4fSDavid du Colombier return strlen(def);
6689a747e4fSDavid du Colombier }
6699a747e4fSDavid du Colombier
6709a747e4fSDavid du Colombier /*
6719a747e4fSDavid du Colombier * get host owner and set it
6729a747e4fSDavid du Colombier */
6739a747e4fSDavid du Colombier void
promptforhostowner(void)6749a747e4fSDavid du Colombier promptforhostowner(void)
6759a747e4fSDavid du Colombier {
6769a747e4fSDavid du Colombier char owner[64], *p;
6779a747e4fSDavid du Colombier
6789a747e4fSDavid du Colombier /* hack for bitsy; can't prompt during boot */
6799a747e4fSDavid du Colombier if(p = getenv("user")){
6809a747e4fSDavid du Colombier writehostowner(p);
681d9306527SDavid du Colombier free(p);
6829a747e4fSDavid du Colombier return;
6839a747e4fSDavid du Colombier }
684d9306527SDavid du Colombier free(p);
6859a747e4fSDavid du Colombier
6869a747e4fSDavid du Colombier strcpy(owner, "none");
6879a747e4fSDavid du Colombier do{
6889a747e4fSDavid du Colombier outin("user", owner, sizeof(owner));
6899a747e4fSDavid du Colombier } while(*owner == 0);
6909a747e4fSDavid du Colombier writehostowner(owner);
6919a747e4fSDavid du Colombier }
6929a747e4fSDavid du Colombier
6932ebbfa15SDavid du Colombier char*
estrappend(char * s,char * fmt,...)6942ebbfa15SDavid du Colombier estrappend(char *s, char *fmt, ...)
6952ebbfa15SDavid du Colombier {
6962ebbfa15SDavid du Colombier char *t;
6972ebbfa15SDavid du Colombier va_list arg;
6982ebbfa15SDavid du Colombier
6992ebbfa15SDavid du Colombier va_start(arg, fmt);
7002ebbfa15SDavid du Colombier t = vsmprint(fmt, arg);
7012ebbfa15SDavid du Colombier if(t == nil)
7022ebbfa15SDavid du Colombier sysfatal("out of memory");
7032ebbfa15SDavid du Colombier va_end(arg);
7042ebbfa15SDavid du Colombier s = erealloc(s, strlen(s)+strlen(t)+1);
7052ebbfa15SDavid du Colombier strcat(s, t);
7062ebbfa15SDavid du Colombier free(t);
7072ebbfa15SDavid du Colombier return s;
7082ebbfa15SDavid du Colombier }
7092ebbfa15SDavid du Colombier
7102ebbfa15SDavid du Colombier
7119a747e4fSDavid du Colombier /*
7129a747e4fSDavid du Colombier * prompt for a string with a possible default response
7139a747e4fSDavid du Colombier */
7142ebbfa15SDavid du Colombier char*
readcons(char * prompt,char * def,int raw)7159a747e4fSDavid du Colombier readcons(char *prompt, char *def, int raw)
7169a747e4fSDavid du Colombier {
7179a747e4fSDavid du Colombier int fdin, fdout, ctl, n;
7189a747e4fSDavid du Colombier char line[10];
7192ebbfa15SDavid du Colombier char *s;
7209a747e4fSDavid du Colombier
7219a747e4fSDavid du Colombier fdin = open("/dev/cons", OREAD);
7229a747e4fSDavid du Colombier if(fdin < 0)
7239a747e4fSDavid du Colombier fdin = 0;
7249a747e4fSDavid du Colombier fdout = open("/dev/cons", OWRITE);
7259a747e4fSDavid du Colombier if(fdout < 0)
7269a747e4fSDavid du Colombier fdout = 1;
7279a747e4fSDavid du Colombier if(def != nil)
7289a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def);
7299a747e4fSDavid du Colombier else
7309a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt);
7319a747e4fSDavid du Colombier if(raw){
7329a747e4fSDavid du Colombier ctl = open("/dev/consctl", OWRITE);
7339a747e4fSDavid du Colombier if(ctl >= 0)
7349a747e4fSDavid du Colombier write(ctl, "rawon", 5);
7359a747e4fSDavid du Colombier } else
7369a747e4fSDavid du Colombier ctl = -1;
7372ebbfa15SDavid du Colombier s = estrdup("");
7389a747e4fSDavid du Colombier for(;;){
7399a747e4fSDavid du Colombier n = read(fdin, line, 1);
7409a747e4fSDavid du Colombier if(n == 0){
7419a747e4fSDavid du Colombier Error:
7429a747e4fSDavid du Colombier close(fdin);
7439a747e4fSDavid du Colombier close(fdout);
7449a747e4fSDavid du Colombier if(ctl >= 0)
7459a747e4fSDavid du Colombier close(ctl);
7462ebbfa15SDavid du Colombier free(s);
7479a747e4fSDavid du Colombier return nil;
7489a747e4fSDavid du Colombier }
7499a747e4fSDavid du Colombier if(n < 0)
7509a747e4fSDavid du Colombier goto Error;
7519a747e4fSDavid du Colombier if(line[0] == 0x7f)
7529a747e4fSDavid du Colombier goto Error;
7539a747e4fSDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){
7549a747e4fSDavid du Colombier if(raw){
7559a747e4fSDavid du Colombier write(ctl, "rawoff", 6);
7569a747e4fSDavid du Colombier write(fdout, "\n", 1);
7579a747e4fSDavid du Colombier }
7589a747e4fSDavid du Colombier close(ctl);
7599a747e4fSDavid du Colombier close(fdin);
7609a747e4fSDavid du Colombier close(fdout);
7612ebbfa15SDavid du Colombier if(*s == 0 && def != nil)
7622ebbfa15SDavid du Colombier s = estrappend(s, "%s", def);
7639a747e4fSDavid du Colombier return s;
7649a747e4fSDavid du Colombier }
7659a747e4fSDavid du Colombier if(line[0] == '\b'){
7662ebbfa15SDavid du Colombier if(strlen(s) > 0)
7672ebbfa15SDavid du Colombier s[strlen(s)-1] = 0;
7689a747e4fSDavid du Colombier } else if(line[0] == 0x15) { /* ^U: line kill */
7692ebbfa15SDavid du Colombier if(def != nil)
7702ebbfa15SDavid du Colombier fprint(fdout, "\n%s[%s]: ", prompt, def);
7712ebbfa15SDavid du Colombier else
7722ebbfa15SDavid du Colombier fprint(fdout, "\n%s: ", prompt);
7732ebbfa15SDavid du Colombier
7742ebbfa15SDavid du Colombier s[0] = 0;
7759a747e4fSDavid du Colombier } else {
7762ebbfa15SDavid du Colombier s = estrappend(s, "%c", line[0]);
7779a747e4fSDavid du Colombier }
7789a747e4fSDavid du Colombier }
7799a747e4fSDavid du Colombier }
7809a747e4fSDavid du Colombier
7819a747e4fSDavid du Colombier /*
7829a747e4fSDavid du Colombier * Insert a key into the keyring.
7839a747e4fSDavid du Colombier * If the public attributes are identical to some other key, replace that one.
7849a747e4fSDavid du Colombier */
7859a747e4fSDavid du Colombier int
replacekey(Key * kn,int before)78670b8e010SDavid du Colombier replacekey(Key *kn, int before)
7879a747e4fSDavid du Colombier {
7889a747e4fSDavid du Colombier int i;
7899a747e4fSDavid du Colombier Key *k;
7909a747e4fSDavid du Colombier
7919a747e4fSDavid du Colombier for(i=0; i<ring->nkey; i++){
7929a747e4fSDavid du Colombier k = ring->key[i];
7939a747e4fSDavid du Colombier if(matchattr(kn->attr, k->attr, nil) && matchattr(k->attr, kn->attr, nil)){
7949a747e4fSDavid du Colombier closekey(k);
7959a747e4fSDavid du Colombier kn->ref++;
7969a747e4fSDavid du Colombier ring->key[i] = kn;
7979a747e4fSDavid du Colombier return 0;
7989a747e4fSDavid du Colombier }
7999a747e4fSDavid du Colombier }
8009a747e4fSDavid du Colombier if(ring->nkey%16 == 0)
8019a747e4fSDavid du Colombier ring->key = erealloc(ring->key, (ring->nkey+16)*sizeof(ring->key[0]));
8029a747e4fSDavid du Colombier kn->ref++;
80370b8e010SDavid du Colombier if(before){
80470b8e010SDavid du Colombier memmove(ring->key+1, ring->key, ring->nkey*sizeof ring->key[0]);
80570b8e010SDavid du Colombier ring->key[0] = kn;
80670b8e010SDavid du Colombier ring->nkey++;
80770b8e010SDavid du Colombier }else
8089a747e4fSDavid du Colombier ring->key[ring->nkey++] = kn;
8099a747e4fSDavid du Colombier return 0;
8109a747e4fSDavid du Colombier }
8119a747e4fSDavid du Colombier
8129a747e4fSDavid du Colombier char*
safecpy(char * to,char * from,int n)8139a747e4fSDavid du Colombier safecpy(char *to, char *from, int n)
8149a747e4fSDavid du Colombier {
8159a747e4fSDavid du Colombier memset(to, 0, n);
8169a747e4fSDavid du Colombier if(n == 1)
8179a747e4fSDavid du Colombier return to;
8189a747e4fSDavid du Colombier if(from==nil)
81914cc0f53SDavid du Colombier sysfatal("safecpy called with from==nil, pc=%#p",
8209a747e4fSDavid du Colombier getcallerpc(&to));
8219a747e4fSDavid du Colombier strncpy(to, from, n-1);
8229a747e4fSDavid du Colombier return to;
8239a747e4fSDavid du Colombier }
8249a747e4fSDavid du Colombier
8259a747e4fSDavid du Colombier Attr*
setattr(Attr * a,char * fmt,...)8269a747e4fSDavid du Colombier setattr(Attr *a, char *fmt, ...)
8279a747e4fSDavid du Colombier {
8289a747e4fSDavid du Colombier char buf[1024];
8299a747e4fSDavid du Colombier va_list arg;
8309a747e4fSDavid du Colombier Attr *b;
8319a747e4fSDavid du Colombier
8329a747e4fSDavid du Colombier va_start(arg, fmt);
8339a747e4fSDavid du Colombier vseprint(buf, buf+sizeof buf, fmt, arg);
8349a747e4fSDavid du Colombier va_end(arg);
8359a747e4fSDavid du Colombier b = _parseattr(buf);
8369a747e4fSDavid du Colombier a = setattrs(a, b);
8379a747e4fSDavid du Colombier setmalloctag(a, getcallerpc(&a));
8389a747e4fSDavid du Colombier _freeattr(b);
8399a747e4fSDavid du Colombier return a;
8409a747e4fSDavid du Colombier }
8419a747e4fSDavid du Colombier
8429a747e4fSDavid du Colombier /*
8439a747e4fSDavid du Colombier * add attributes in list b to list a. If any attributes are in
8449a747e4fSDavid du Colombier * both lists, replace those in a by those in b.
8459a747e4fSDavid du Colombier */
8469a747e4fSDavid du Colombier Attr*
setattrs(Attr * a,Attr * b)8479a747e4fSDavid du Colombier setattrs(Attr *a, Attr *b)
8489a747e4fSDavid du Colombier {
8499a747e4fSDavid du Colombier int found;
8509a747e4fSDavid du Colombier Attr **l, *freea;
8519a747e4fSDavid du Colombier
8529a747e4fSDavid du Colombier for(; b; b=b->next){
8539a747e4fSDavid du Colombier found = 0;
8549a747e4fSDavid du Colombier for(l=&a; *l; ){
8552ebbfa15SDavid du Colombier if(strcmp(b->name, (*l)->name) == 0){
8569a747e4fSDavid du Colombier switch(b->type){
8579a747e4fSDavid du Colombier case AttrNameval:
8589a747e4fSDavid du Colombier if(!found){
8599a747e4fSDavid du Colombier found = 1;
8602ebbfa15SDavid du Colombier free((*l)->val);
8612ebbfa15SDavid du Colombier (*l)->val = estrdup(b->val);
8629a747e4fSDavid du Colombier (*l)->type = AttrNameval;
8639a747e4fSDavid du Colombier l = &(*l)->next;
8649a747e4fSDavid du Colombier }else{
8659a747e4fSDavid du Colombier freea = *l;
8669a747e4fSDavid du Colombier *l = (*l)->next;
8679a747e4fSDavid du Colombier freea->next = nil;
8689a747e4fSDavid du Colombier _freeattr(freea);
8699a747e4fSDavid du Colombier }
8709a747e4fSDavid du Colombier break;
8719a747e4fSDavid du Colombier case AttrQuery:
872f0ed0fb6SDavid du Colombier goto continue2;
8739a747e4fSDavid du Colombier }
8749a747e4fSDavid du Colombier }else
8759a747e4fSDavid du Colombier l = &(*l)->next;
8769a747e4fSDavid du Colombier }
8779a747e4fSDavid du Colombier if(found == 0){
8782ebbfa15SDavid du Colombier *l = _mkattr(b->type, b->name, b->val, nil);
8799a747e4fSDavid du Colombier setmalloctag(*l, getcallerpc(&a));
8809a747e4fSDavid du Colombier }
881f0ed0fb6SDavid du Colombier continue2:;
8829a747e4fSDavid du Colombier }
8839a747e4fSDavid du Colombier return a;
8849a747e4fSDavid du Colombier }
8859a747e4fSDavid du Colombier
8869a747e4fSDavid du Colombier void
setmalloctaghere(void * v)8879a747e4fSDavid du Colombier setmalloctaghere(void *v)
8889a747e4fSDavid du Colombier {
8899a747e4fSDavid du Colombier setmalloctag(v, getcallerpc(&v));
8909a747e4fSDavid du Colombier }
8919a747e4fSDavid du Colombier
8929a747e4fSDavid du Colombier Attr*
sortattr(Attr * a)8939a747e4fSDavid du Colombier sortattr(Attr *a)
8949a747e4fSDavid du Colombier {
8959a747e4fSDavid du Colombier int i;
8969a747e4fSDavid du Colombier Attr *anext, *a0, *a1, **l;
8979a747e4fSDavid du Colombier
8989a747e4fSDavid du Colombier if(a == nil || a->next == nil)
8999a747e4fSDavid du Colombier return a;
9009a747e4fSDavid du Colombier
9019a747e4fSDavid du Colombier /* cut list in halves */
9029a747e4fSDavid du Colombier a0 = nil;
9039a747e4fSDavid du Colombier a1 = nil;
9049a747e4fSDavid du Colombier i = 0;
9059a747e4fSDavid du Colombier for(; a; a=anext){
9069a747e4fSDavid du Colombier anext = a->next;
9079a747e4fSDavid du Colombier if(i++%2){
9089a747e4fSDavid du Colombier a->next = a0;
9099a747e4fSDavid du Colombier a0 = a;
9109a747e4fSDavid du Colombier }else{
9119a747e4fSDavid du Colombier a->next = a1;
9129a747e4fSDavid du Colombier a1 = a;
9139a747e4fSDavid du Colombier }
9149a747e4fSDavid du Colombier }
9159a747e4fSDavid du Colombier
9169a747e4fSDavid du Colombier /* sort */
9179a747e4fSDavid du Colombier a0 = sortattr(a0);
9189a747e4fSDavid du Colombier a1 = sortattr(a1);
9199a747e4fSDavid du Colombier
9209a747e4fSDavid du Colombier /* merge */
9219a747e4fSDavid du Colombier l = &a;
9229a747e4fSDavid du Colombier while(a0 || a1){
9239a747e4fSDavid du Colombier if(a1==nil){
9249a747e4fSDavid du Colombier anext = a0;
9259a747e4fSDavid du Colombier a0 = a0->next;
9269a747e4fSDavid du Colombier }else if(a0==nil){
9279a747e4fSDavid du Colombier anext = a1;
9289a747e4fSDavid du Colombier a1 = a1->next;
9292ebbfa15SDavid du Colombier }else if(strcmp(a0->name, a1->name) < 0){
9309a747e4fSDavid du Colombier anext = a0;
9319a747e4fSDavid du Colombier a0 = a0->next;
9329a747e4fSDavid du Colombier }else{
9339a747e4fSDavid du Colombier anext = a1;
9349a747e4fSDavid du Colombier a1 = a1->next;
9359a747e4fSDavid du Colombier }
9369a747e4fSDavid du Colombier *l = anext;
9379a747e4fSDavid du Colombier l = &(*l)->next;
9389a747e4fSDavid du Colombier }
9399a747e4fSDavid du Colombier *l = nil;
9409a747e4fSDavid du Colombier return a;
9419a747e4fSDavid du Colombier }
9429a747e4fSDavid du Colombier
9439a747e4fSDavid du Colombier int
toosmall(Fsstate * fss,uint n)9449a747e4fSDavid du Colombier toosmall(Fsstate *fss, uint n)
9459a747e4fSDavid du Colombier {
9469a747e4fSDavid du Colombier fss->rpc.nwant = n;
9479a747e4fSDavid du Colombier return RpcToosmall;
9489a747e4fSDavid du Colombier }
9499a747e4fSDavid du Colombier
9509a747e4fSDavid du Colombier void
writehostowner(char * owner)9519a747e4fSDavid du Colombier writehostowner(char *owner)
9529a747e4fSDavid du Colombier {
9539a747e4fSDavid du Colombier int fd;
9549a747e4fSDavid du Colombier char *s;
9559a747e4fSDavid du Colombier
9569a747e4fSDavid du Colombier if((s = strchr(owner,'@')) != nil){
9579a747e4fSDavid du Colombier *s++ = 0;
9589a747e4fSDavid du Colombier strncpy(secstore, s, (sizeof secstore)-1);
9599a747e4fSDavid du Colombier }
9609a747e4fSDavid du Colombier fd = open("#c/hostowner", OWRITE);
9619a747e4fSDavid du Colombier if(fd >= 0){
9629a747e4fSDavid du Colombier if(fprint(fd, "%s", owner) < 0)
963d854de59SDavid du Colombier fprint(2, "factotum: setting #c/hostowner to %q: %r\n",
964d854de59SDavid du Colombier owner);
9659a747e4fSDavid du Colombier close(fd);
9669a747e4fSDavid du Colombier }
9679a747e4fSDavid du Colombier }
9689a747e4fSDavid du Colombier
9695d459b5aSDavid du Colombier int
attrnamefmt(Fmt * fmt)9705d459b5aSDavid du Colombier attrnamefmt(Fmt *fmt)
9715d459b5aSDavid du Colombier {
9725d459b5aSDavid du Colombier char *b, buf[1024], *ebuf;
9735d459b5aSDavid du Colombier Attr *a;
9745d459b5aSDavid du Colombier
9755d459b5aSDavid du Colombier ebuf = buf+sizeof buf;
9765d459b5aSDavid du Colombier b = buf;
9775d459b5aSDavid du Colombier strcpy(buf, " ");
9785d459b5aSDavid du Colombier for(a=va_arg(fmt->args, Attr*); a; a=a->next){
9795d459b5aSDavid du Colombier if(a->name == nil)
9805d459b5aSDavid du Colombier continue;
9812ebbfa15SDavid du Colombier b = seprint(b, ebuf, " %q?", a->name);
9825d459b5aSDavid du Colombier }
9835d459b5aSDavid du Colombier return fmtstrcpy(fmt, buf+1);
9845d459b5aSDavid du Colombier }
985260f7b65SDavid du Colombier
986260f7b65SDavid du Colombier void
disablekey(Key * k)987260f7b65SDavid du Colombier disablekey(Key *k)
988260f7b65SDavid du Colombier {
989260f7b65SDavid du Colombier Attr *a;
990260f7b65SDavid du Colombier
991b05f4f54SDavid du Colombier if(sflag) /* not on servers */
992b05f4f54SDavid du Colombier return;
993260f7b65SDavid du Colombier for(a=k->attr; a; a=a->next){
994260f7b65SDavid du Colombier if(a->type==AttrNameval && strcmp(a->name, "disabled") == 0)
995260f7b65SDavid du Colombier return;
996260f7b65SDavid du Colombier if(a->next == nil)
997260f7b65SDavid du Colombier break;
998260f7b65SDavid du Colombier }
999260f7b65SDavid du Colombier if(a)
1000260f7b65SDavid du Colombier a->next = _mkattr(AttrNameval, "disabled", "by.factotum", nil);
1001260f7b65SDavid du Colombier else
1002260f7b65SDavid du Colombier k->attr = _mkattr(AttrNameval, "disabled", "by.factotum", nil); /* not reached: always a proto attribute */
1003260f7b65SDavid du Colombier }
1004