📄 keyfs.c
字号:
if(strcmp(data, status[i]) == 0){ f->user->status = i; break; } if(i == Smax) return "unknown status"; f->user->bad = 0; thdr.count = n; break; case Qexpire: data[n] = '\0'; if(p = strchr(data, '\n')) *p = '\0'; else p = &data[n]; if(strcmp(data, "never") == 0) expire = 0; else{ expire = strtoul(data, &data, 10); if(data != p) return "bad expiration date"; } f->user->expire = expire; f->user->warnings = 0; thdr.count = n; break; case Qlog: data[n] = '\0'; if(strcmp(data, "good") == 0) f->user->bad = 0; else f->user->bad++; if(f->user->bad && ((f->user->bad)%MAXBAD) == 0) f->user->purgatory = time(0) + f->user->bad; return 0; case Qwarnings: data[n] = '\0'; f->user->warnings = strtoul(data, 0, 10); thdr.count = n; break; case Qroot: case Quser: default: return "permission denied"; } writeusers(); return 0;}char *Remove(Fid *f){ if(!f->busy) return "permission denied"; if(f->qtype == Qwarnings) f->user->warnings = 0; else if(f->qtype == Quser) removeuser(f->user); else { Clunk(f); return "permission denied"; } Clunk(f); writeusers(); return 0;}char *Stat(Fid *f){ static uchar statbuf[1024]; if(!f->busy) return "stat on unattached fid"; thdr.nstat = dostat(f->user, f->qtype, statbuf, sizeof statbuf); if(thdr.nstat <= BIT16SZ) return "stat buffer too small"; thdr.stat = statbuf; return 0;}char *Wstat(Fid *f){ Dir d; int n; char buf[1024]; if(!f->busy || f->qtype != Quser) return "permission denied"; if(rhdr.nstat > sizeof buf) return "wstat buffer too big"; if(convM2D(rhdr.stat, rhdr.nstat, &d, buf) == 0) return "bad stat buffer"; n = strlen(d.name); if(n == 0 || n >= Namelen) return "bad user name"; if(finduser(d.name)) return "user already exists"; if(!removeuser(f->user)) return "user previously removed"; free(f->user->name); f->user->name = strdup(d.name); if(f->user->name == nil) error("wstat: malloc failed: %r"); insertuser(f->user); writeusers(); return 0;}Qidmkqid(User *u, ulong qtype){ Qid q; q.vers = 0; q.path = qtype; if(u) q.path |= u->uniq * 0x100; if(qtype == Quser || qtype == Qroot) q.type = QTDIR; else q.type = QTFILE; return q;}intdostat(User *user, ulong qtype, void *p, int n){ Dir d; if(qtype == Quser) d.name = user->name; else d.name = qinfo[qtype]; d.uid = d.gid = d.muid = "auth"; d.qid = mkqid(user, qtype); if(d.qid.type & QTDIR) d.mode = 0777|DMDIR; else d.mode = 0666; d.atime = d.mtime = time(0); d.length = 0; return convD2M(&d, p, n);}intpassline(Biobuf *b, void *vbuf){ char *buf = vbuf; if(Bread(b, buf, KEYDBLEN) != KEYDBLEN) return 0; decrypt(authkey, buf, KEYDBLEN); buf[Namelen-1] = '\0'; return 1;}voidrandombytes(uchar *p, int len){ int i, fd; fd = open("/dev/random", OREAD); if(fd < 0){ fprint(2, "keyfs: can't open /dev/random, using rand()\n"); srand(time(0)); for(i = 0; i < len; i++) p[i] = rand(); return; } read(fd, p, len); close(fd);}voidoldCBCencrypt(char *key7, uchar *p, int len){ uchar ivec[8]; uchar key[8]; DESstate s; memset(ivec, 0, 8); des56to64((uchar*)key7, key); setupDESstate(&s, key, ivec); desCBCencrypt((uchar*)p, len, &s);}voidoldCBCdecrypt(char *key7, uchar *p, int len){ uchar ivec[8]; uchar key[8]; DESstate s; memset(ivec, 0, 8); des56to64((uchar*)key7, key); setupDESstate(&s, key, ivec); desCBCdecrypt((uchar*)p, len, &s);}voidwriteusers(void){ int fd, i, nu; User *u; uchar *p, *buf; ulong expire; /* count users */ nu = 0; for(i = 0; i < Nuser; i++) for(u = users[i]; u; u = u->link) nu++; /* pack into buffer */ buf = malloc(KEYDBOFF + nu*KEYDBLEN); if(buf == 0){ fprint(2, "keyfs: can't write keys file, out of memory\n"); return; } p = buf; randombytes(p, KEYDBOFF); p += KEYDBOFF; for(i = 0; i < Nuser; i++) for(u = users[i]; u; u = u->link){ strncpy((char*)p, u->name, Namelen); p += Namelen; memmove(p, u->key, DESKEYLEN); p += DESKEYLEN; *p++ = u->status; *p++ = u->warnings; expire = u->expire; *p++ = expire; *p++ = expire >> 8; *p++ = expire >> 16; *p++ = expire >> 24; memmove(p, u->secret, SECRETLEN); p += SECRETLEN; } /* encrypt */ oldCBCencrypt(authkey, buf, p - buf); /* write file */ fd = create(userkeys, OWRITE, 0660); if(fd < 0){ free(buf); fprint(2, "keyfs: can't write keys file\n"); return; } if(write(fd, buf, p - buf) != (p - buf)) fprint(2, "keyfs: can't write keys file\n"); free(buf); close(fd);}intreadusers(void){ int fd, i, n, nu; uchar *p, *buf, *ep; User *u; Dir *d; /* read file into an array */ fd = open(userkeys, OREAD); if(fd < 0) return 0; d = dirfstat(fd); if(d == nil){ close(fd); return 0; } buf = malloc(d->length); if(buf == 0){ close(fd); free(d); return 0; } n = readn(fd, buf, d->length); close(fd); free(d); if(n != d->length){ free(buf); return 0; } /* decrypt */ n -= n % KEYDBLEN; oldCBCdecrypt(authkey, buf, n); /* unpack */ nu = 0; for(i = KEYDBOFF; i < n; i += KEYDBLEN){ ep = buf + i; u = finduser((char*)ep); if(u == 0) u = installuser((char*)ep); memmove(u->key, ep + Namelen, DESKEYLEN); p = ep + Namelen + DESKEYLEN; u->status = *p++; u->warnings = *p++; if(u->status >= Smax) fprint(2, "keyfs: warning: bad status in key file\n"); u->expire = p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24); p += 4; memmove(u->secret, p, SECRETLEN); u->secret[SECRETLEN-1] = 0; nu++; } free(buf); print("%d keys read\n", nu); return 1;}User *installuser(char *name){ User *u; int h; h = hash(name); u = emalloc(sizeof *u); u->name = strdup(name); if(u->name == nil) error("malloc failed: %r"); u->removed = 0; u->ref = 0; u->purgatory = 0; u->expire = 0; u->status = Sok; u->bad = 0; u->warnings = 0; u->uniq = uniq++; u->link = users[h]; users[h] = u; return u;}User *finduser(char *name){ User *u; for(u = users[hash(name)]; u; u = u->link) if(strcmp(name, u->name) == 0) return u; return 0;}intremoveuser(User *user){ User *u, **last; char *name; user->removed = 1; name = user->name; last = &users[hash(name)]; for(u = *last; u; u = *last){ if(strcmp(name, u->name) == 0){ *last = u->link; return 1; } last = &u->link; } return 0;}voidinsertuser(User *user){ int h; user->removed = 0; h = hash(user->name); user->link = users[h]; users[h] = user;}ulonghash(char *s){ ulong h; h = 0; while(*s) h = (h << 1) ^ *s++; return h % Nuser;}Fid *findfid(int fid){ Fid *f, *ff; ff = 0; for(f = fids; f; f = f->next) if(f->fid == fid) return f; else if(!ff && !f->busy) ff = f; if(ff){ ff->fid = fid; return ff; } f = emalloc(sizeof *f); f->fid = fid; f->busy = 0; f->user = 0; f->next = fids; fids = f; return f;}voidio(int in, int out){ char *err; int n; long now, lastwarning; /* after restart, let the system settle for 5 mins before warning */ lastwarning = time(0) - 24*60*60 + 5*60; for(;;){ n = read9pmsg(in, mdata, messagesize); if(n == 0) continue; if(n < 0) error("mount read %d", n); if(convM2S(mdata, n, &rhdr) == 0) continue; if(newkeys()) readusers(); thdr.data = (char*)mdata + IOHDRSZ; thdr.fid = rhdr.fid; if(!fcalls[rhdr.type]) err = "fcall request"; else err = (*fcalls[rhdr.type])(findfid(rhdr.fid)); thdr.tag = rhdr.tag; thdr.type = rhdr.type+1; if(err){ thdr.type = Rerror; thdr.ename = err; } n = convS2M(&thdr, mdata, messagesize); if(write(out, mdata, n) != n) error("mount write"); now = time(0); if(warnarg && (now - lastwarning > 24*60*60)){ syslog(0, "auth", "keyfs starting warnings: %lux %lux", now, lastwarning); warning(); lastwarning = now; } }}intnewkeys(void){ Dir *d; static long ftime; d = dirstat(userkeys); if(d == nil) return 0; if(d->mtime > ftime){ ftime = d->mtime; free(d); return 1; } free(d); return 0;}void *emalloc(ulong n){ void *p; if(p = malloc(n)) return p; error("out of memory"); return 0; /* not reached */}voidwarning(void){ int i; char buf[64]; snprint(buf, sizeof buf, "-%s", warnarg); switch(rfork(RFPROC|RFNAMEG|RFNOTEG|RFNOWAIT|RFENVG|RFFDG)){ case 0: i = open("/sys/log/auth", OWRITE); if(i >= 0){ dup(i, 2); seek(2, 0, 2); close(i); } execl("/bin/auth/warning", "warning", warnarg, nil); error("can't exec warning"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -