📄 util.c
字号:
#include "dat.h"static char secstore[100]; /* server name *//* bind in the default network and cs */static intbindnetcs(void){ int srvfd; if(access("/net/tcp", AEXIST) < 0) bind("#I", "/net", MBEFORE); if(access("/net/cs", AEXIST) < 0){ if((srvfd = open("#s/cs", ORDWR)) >= 0){ if(mount(srvfd, -1, "/net", MBEFORE, "") >= 0) return 0; close(srvfd); } return -1; } return 0;}int_authdial(char *net, char *authdom){ int fd, vanilla; vanilla = net==nil || strcmp(net, "/net")==0; if(!vanilla || bindnetcs()>=0) return authdial(net, authdom); /* * If we failed to mount /srv/cs, assume that * we're still bootstrapping the system and dial * the one auth server passed to us on the command line. * In normal operation, it is important *not* to do this, * because the bootstrap auth server is only good for * a single auth domain. * * The ticket request code should really check the * remote authentication domain too. */ /* use the auth sever passed to us as an arg */ if(authaddr == nil) return -1; fd = dial(netmkaddr(authaddr, "il", "566"), 0, 0, 0); if(fd >= 0) return fd; return dial(netmkaddr(authaddr, "tcp", "567"), 0, 0, 0);}intsecdial(void){ char *p, buf[80], *f[3]; int fd, nf; p = secstore; /* take it from writehostowner, if set there */ if(*p == 0) /* else use the authserver */ p = "$auth"; if(bindnetcs() >= 0) return dial(netmkaddr(p, "net", "secstore"), 0, 0, 0); /* translate $auth ourselves. * authaddr is something like il!host!566 or tcp!host!567. * extract host, accounting for a change of format to something * like il!host or tcp!host or host. */ if(strcmp(p, "$auth")==0){ if(authaddr == nil) return -1; safecpy(buf, authaddr, sizeof buf); nf = getfields(buf, f, nelem(f), 0, "!"); switch(nf){ default: return -1; case 1: p = f[0]; break; case 2: case 3: p = f[1]; break; } } fd = dial(netmkaddr(p, "tcp", "5356"), 0, 0, 0); if(fd >= 0) return fd; return -1;}/* * prompt user for a key. don't care about memory leaks, runs standalone */static Attr*promptforkey(char *params){ char *v; int fd; Attr *a, *attr; char *def; fd = open("/dev/cons", ORDWR); if(fd < 0) sysfatal("opening /dev/cons: %r"); attr = _parseattr(params); fprint(fd, "\n!Adding key:"); for(a=attr; a; a=a->next) if(a->type != AttrQuery && a->name[0] != '!') fprint(fd, " %q=%q", a->name, a->val); fprint(fd, "\n"); for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]=='!') continue; def = nil; if(strcmp(v, "user") == 0) def = getuser(); a->val = readcons(v, def, 0); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]!='!') continue; def = nil; if(strcmp(v+1, "user") == 0) def = getuser(); a->val = readcons(v+1, def, 1); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } fprint(fd, "!\n"); close(fd); return attr;}/* * send a key to the mounted factotum */static intsendkey(Attr *attr){ int fd, rv; char buf[1024]; fd = open("/mnt/factotum/ctl", ORDWR); if(fd < 0) sysfatal("opening /mnt/factotum/ctl: %r"); rv = fprint(fd, "key %A\n", attr); read(fd, buf, sizeof buf); close(fd); return rv;}/* askuser */voidaskuser(char *params){ Attr *attr; attr = promptforkey(params); if(attr == nil) sysfatal("no key supplied"); if(sendkey(attr) < 0) sysfatal("sending key to factotum: %r");}ulong conftaggen;intcanusekey(Fsstate *fss, Key *k){ int i; if(_strfindattr(k->attr, "confirm")){ for(i=0; i<fss->nconf; i++) if(fss->conf[i].key == k) return fss->conf[i].canuse; if(fss->nconf%16 == 0) fss->conf = erealloc(fss->conf, (fss->nconf+16)*(sizeof(fss->conf[0]))); fss->conf[fss->nconf].key = k; k->ref++; fss->conf[fss->nconf].canuse = -1; fss->conf[fss->nconf].tag = conftaggen++; fss->nconf++; return -1; } return 1;}/* closekey */voidclosekey(Key *k){ if(k == nil) return; if(--k->ref != 0) return; if(k->proto && k->proto->closekey) (*k->proto->closekey)(k); _freeattr(k->attr); _freeattr(k->privattr); k->attr = (void*)~1; k->privattr = (void*)~1; k->proto = nil; free(k);}static uchar*pstring(uchar *p, uchar *e, char *s){ uint n; if(p == nil) return nil; if(s == nil) s = ""; n = strlen(s); if(p+n+BIT16SZ >= e) return nil; PBIT16(p, n); p += BIT16SZ; memmove(p, s, n); p += n; return p;}static uchar*pcarray(uchar *p, uchar *e, uchar *s, uint n){ if(p == nil) return nil; if(s == nil){ if(n > 0) sysfatal("pcarray"); s = (uchar*)""; } if(p+n+BIT16SZ >= e) return nil; PBIT16(p, n); p += BIT16SZ; memmove(p, s, n); p += n; return p;}uchar*convAI2M(AuthInfo *ai, uchar *p, int n){ uchar *e = p+n; p = pstring(p, e, ai->cuid); p = pstring(p, e, ai->suid); p = pstring(p, e, ai->cap); p = pcarray(p, e, ai->secret, ai->nsecret); return p;}intfailure(Fsstate *s, char *fmt, ...){ char e[ERRMAX]; va_list arg; if(fmt == nil) rerrstr(s->err, sizeof(s->err)); else { va_start(arg, fmt); snprint(e, sizeof e, fmt, arg); va_end(arg); strecpy(s->err, s->err+sizeof(s->err), e); errstr(e, sizeof e); } flog("%d: failure %s", s->seqnum, s->err); return RpcFailure;}static inthasqueries(Attr *a){ for(; a; a=a->next) if(a->type == AttrQuery) return 1; return 0;}char *ignored[] = { "role", "disabled",};static intignoreattr(char *s){ int i; for(i=0; i<nelem(ignored); i++) if(strcmp(ignored[i], s)==0) return 1; return 0;}Keyinfo*mkkeyinfo(Keyinfo *k, Fsstate *fss, Attr *attr){ memset(k, 0, sizeof *k); k->fss = fss; k->user = fss->sysuser; if(attr) k->attr = attr; else k->attr = fss->attr; return k;}intfindkey(Key **ret, Keyinfo *ki, char *fmt, ...){ int i, s, nmatch; char buf[1024], *p, *who; va_list arg; Attr *a, *attr0, *attr1, *attr2, *attr3, **l; Key *k; *ret = nil; who = ki->user; attr0 = ki->attr; if(fmt){ va_start(arg, fmt); vseprint(buf, buf+sizeof buf, fmt, arg); va_end(arg); attr1 = _parseattr(buf); }else attr1 = nil; if(who && strcmp(who, owner) == 0) who = nil; if(who){ snprint(buf, sizeof buf, "owner=%q", who); attr2 = _parseattr(buf); attr3 = _parseattr("owner=*"); }else attr2 = attr3 = nil; p = _strfindattr(attr0, "proto"); if(p == nil) p = _strfindattr(attr1, "proto"); if(p && findproto(p) == nil){ werrstr("unknown protocol %s", p); _freeattr(attr1); _freeattr(attr2); _freeattr(attr3); return failure(ki->fss, nil); } nmatch = 0; for(i=0; i<ring->nkey; i++){ k = ring->key[i]; if(_strfindattr(k->attr, "disabled") && !ki->usedisabled) continue; if(matchattr(attr0, k->attr, k->privattr) && matchattr(attr1, k->attr, k->privattr)){ /* check ownership */ if(!matchattr(attr2, k->attr, nil) && !matchattr(attr3, k->attr, nil)) continue; if(nmatch++ < ki->skip) continue; if(!ki->noconf){ switch(canusekey(ki->fss, k)){ case -1: _freeattr(attr1); return RpcConfirm; case 0: continue; case 1: break; } } _freeattr(attr1); _freeattr(attr2); _freeattr(attr3); k->ref++; *ret = k; return RpcOk; } } flog("%d: no key matches %A %A %A %A", ki->fss->seqnum, attr0, attr1, attr2, attr3); werrstr("no key matches %A %A", attr0, attr1); _freeattr(attr2); _freeattr(attr3); s = RpcFailure; if(askforkeys && who==nil && (hasqueries(attr0) || hasqueries(attr1))){ if(nmatch == 0){ attr0 = _copyattr(attr0); for(l=&attr0; *l; l=&(*l)->next) ; *l = attr1; for(l=&attr0; *l; ){ if(ignoreattr((*l)->name)){ a = *l; *l = (*l)->next; a->next = nil; _freeattr(a); }else l = &(*l)->next; } attr0 = sortattr(attr0); snprint(ki->fss->keyinfo, sizeof ki->fss->keyinfo, "%A", attr0); _freeattr(attr0); attr1 = nil; /* attr1 was linked to attr0 */ }else ki->fss->keyinfo[0] = '\0'; s = RpcNeedkey; } _freeattr(attr1); if(s == RpcFailure) return failure(ki->fss, nil); /* loads error string */ return s;}intfindp9authkey(Key **k, Fsstate *fss){ char *dom; Keyinfo ki; /* * We don't use fss->attr here because we don't * care about what the user name is set to, for instance. */ mkkeyinfo(&ki, fss, nil); ki.attr = nil; ki.user = nil; if(dom = _strfindattr(fss->attr, "dom")) return findkey(k, &ki, "proto=p9sk1 dom=%q role=server user?", dom); else return findkey(k, &ki, "proto=p9sk1 role=server dom? user?");}Proto*findproto(char *name){ int i; for(i=0; prototab[i]; i++) if(strcmp(name, prototab[i]->name) == 0) return prototab[i]; return nil;}char*getnvramkey(int flag, char **secstorepw){ char *s; Nvrsafe safe; char spw[CONFIGLEN+1]; int i; memset(&safe, 0, sizeof safe); /* * readnvram can return -1 meaning nvram wasn't written, * but safe still holds good data. */ if(readnvram(&safe, flag)<0 && safe.authid[0]==0) return nil; /* * we're using the config area to hold the secstore * password. if there's anything there, return it. */ memmove(spw, safe.config, CONFIGLEN); spw[CONFIGLEN] = 0; if(spw[0] != 0) *secstorepw = estrdup(spw); /* * only use nvram key if it is non-zero */ for(i = 0; i < DESKEYLEN; i++) if(safe.machkey[i] != 0) break; if(i == DESKEYLEN) return nil; s = emalloc(512); fmtinstall('H', encodefmt); sprint(s, "key proto=p9sk1 user=%q dom=%q !hex=%.*H !password=______", safe.authid, safe.authdom, DESKEYLEN, safe.machkey); writehostowner(safe.authid); return s;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -