⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <authsrv.h>#include <fcall.h>#include <bio.h>#include <mp.h>#include <libsec.h>#include "authcmdlib.h"char authkey[8];typedef struct Fid	Fid;typedef struct User	User;enum{	Qroot,	Quser,	Qkey,	Qsecret,	Qlog,	Qstatus,	Qexpire,	Qwarnings,	Qmax,	Nuser	= 512,	MAXBAD	= 10,			/* max number of bad attempts before disabling the account */	Namelen	= ANAMELEN,		/* file must be randomly addressible, so names have fixed length */};enum{	Sok,	Sdisabled,	Smax,};struct Fid{	int	fid;	ulong	qtype;	User	*user;	int	busy;	Fid	*next;};struct User{	char	*name;	char	key[DESKEYLEN];	char	secret[SECRETLEN];	ulong	expire;			/* 0 == never */	uchar	status;	ulong	bad;			/* number of consecutive bad authentication attempts */	int	ref;	char	removed;	uchar	warnings;	long	purgatory;		/* time purgatory ends */	ulong	uniq;	User	*link;};char	*qinfo[Qmax] = {	[Qroot]		"keys",	[Quser]		".",	[Qkey]		"key",	[Qsecret]	"secret",	[Qlog]		"log",	[Qexpire]	"expire",	[Qstatus]	"status",	[Qwarnings]	"warnings",};char	*status[Smax] = {	[Sok]		"ok",	[Sdisabled]	"disabled",};Fid	*fids;User	*users[Nuser];char	*userkeys;int	nuser;ulong	uniq = 1;Fcall	rhdr,	thdr;int	usepass;char	*warnarg;uchar	mdata[8192 + IOHDRSZ];int	messagesize = sizeof mdata;int	readusers(void);ulong	hash(char*);Fid	*findfid(int);User	*finduser(char*);User	*installuser(char*);int	removeuser(User*);void	insertuser(User*);void	writeusers(void);void	io(int, int);void	*emalloc(ulong);Qid	mkqid(User*, ulong);int	dostat(User*, ulong, void*, int);int	newkeys(void);void	warning(void);char	*Auth(Fid*), *Attach(Fid*), *Version(Fid*),	*Flush(Fid*), *Walk(Fid*),	*Open(Fid*), *Create(Fid*),	*Read(Fid *), *Write(Fid*), *Clunk(Fid*),	*Remove(Fid *), *Stat(Fid*), *Wstat(Fid*);char 	*(*fcalls[])(Fid*) = {	[Tattach]	Attach,	[Tauth]	Auth,	[Tclunk]	Clunk,	[Tcreate]	Create,	[Tflush]	Flush,	[Topen]		Open,	[Tread]		Read,	[Tremove]	Remove,	[Tstat]		Stat,	[Tversion]	Version,	[Twalk]		Walk,	[Twrite]	Write,	[Twstat]	Wstat,};voidmain(int argc, char *argv[]){	char *mntpt;	int p[2];	mntpt = "/mnt/keys";	ARGBEGIN{	case 'm':		mntpt = ARGF();		break;	case 'w':		warnarg = ARGF();		break;	case 'p':		usepass = 1;		break;	}ARGEND	argv0 = "keyfs";	userkeys = "/adm/keys";	if(argc > 0)		userkeys = argv[0];	if(pipe(p) < 0)		error("can't make pipe: %r");	if(usepass) {		getpass(authkey, nil, 0, 0);	} else {		if(!getauthkey(authkey))			print("keyfs: warning: can't read /dev/key\n");	}	switch(rfork(RFPROC|RFNAMEG|RFNOTEG|RFNOWAIT|RFENVG|RFFDG)){	case 0:		close(p[0]);		io(p[1], p[1]);		exits(0);	case -1:		error("fork");	default:		close(p[1]);		if(mount(p[0], -1, mntpt, MREPL|MCREATE, "") < 0)			error("can't mount: %r");		exits(0);	}}char *Flush(Fid *f){	USED(f);	return 0;}char *Auth(Fid *){	return "keyfs: authentication not required";}char *Attach(Fid *f){	if(f->busy)		Clunk(f);	f->user = 0;	f->qtype = Qroot;	f->busy = 1;	thdr.qid = mkqid(f->user, f->qtype);	return 0;}char*Version(Fid*){	Fid *f;	for(f = fids; f; f = f->next)		if(f->busy)			Clunk(f);	if(rhdr.msize > sizeof mdata)		thdr.msize = sizeof mdata;	else		thdr.msize = rhdr.msize;	messagesize = thdr.msize;	if(strncmp(rhdr.version, "9P2000", 6) != 0)		return "bad 9P version";	thdr.version = "9P2000";	return 0;}char *Walk(Fid *f){	char *name, *err;	int i, j, max;	Fid *nf;	ulong qtype;	User *user;	if(!f->busy)		return "walk of unused fid";	nf = nil;	qtype = f->qtype;	user = f->user;	if(rhdr.fid != rhdr.newfid){		nf = findfid(rhdr.newfid);		if(nf->busy)			return "fid in use";		f = nf;	/* walk f */	}	err = nil;	i = 0;	if(rhdr.nwname > 0){		for(; i<rhdr.nwname; i++){			if(i >= MAXWELEM){				err = "too many path name elements";				break;			}			name = rhdr.wname[i];			switch(qtype){			case Qroot:				if(strcmp(name, "..") == 0)					goto Accept;				user = finduser(name);				if(!user)					goto Out;				qtype = Quser;			Accept:				thdr.wqid[i] = mkqid(user, qtype);				break;			case Quser:				if(strcmp(name, "..") == 0) {					qtype = Qroot;					user = 0;					goto Accept;				}				max = Qmax;				for(j = Quser + 1; j < Qmax; j++)					if(strcmp(name, qinfo[j]) == 0){						qtype = j;						break;					}				if(j < max)					goto Accept;				goto Out;			default:				err = "file is not a directory";				goto Out;			}		}	    Out:		if(i < rhdr.nwname && err == nil)			err = "file not found";	}	if(err != nil){		return err;	}	/* if we cloned and then completed the walk, update new fid */	if(rhdr.fid != rhdr.newfid && i == rhdr.nwname){		nf->busy = 1;		nf->qtype = qtype;		if(nf->user = user)			nf->user->ref++;	}else if(nf == nil && rhdr.nwname > 0){	/* walk without clone (rare) */		Clunk(f);		f->busy = 1;		f->qtype = qtype;		if(f->user = user)			f->user->ref++;	}	thdr.nwqid = i;	return 0;}char *Clunk(Fid *f){	f->busy = 0;	if(f->user && --f->user->ref == 0 && f->user->removed) {		free(f->user->name);		free(f->user);	}	f->user = 0;	return 0;}char *Open(Fid *f){	int mode;	if(!f->busy)		return "open of unused fid";	mode = rhdr.mode;	if(f->qtype == Quser && (mode & (OWRITE|OTRUNC)))		return "user already exists";	thdr.qid = mkqid(f->user, f->qtype);	thdr.iounit = messagesize - IOHDRSZ;	return 0;}char *Create(Fid *f){	char *name;	long perm;	if(!f->busy)		return "create of unused fid";	name = rhdr.name;	if(f->user){		return "permission denied";	}else{		perm = rhdr.perm;		if(!(perm & DMDIR))			return "permission denied";		if(strcmp(name, "") == 0)			return "empty file name";		if(strlen(name) >= Namelen)			return "file name too long";		if(finduser(name))			return "user already exists";		f->user = installuser(name);		f->user->ref++;		f->qtype = Quser;	}	thdr.qid = mkqid(f->user, f->qtype);	thdr.iounit = messagesize - IOHDRSZ;	writeusers();	return 0;}char *Read(Fid *f){	User *u;	char *data;	ulong off, n, m;	int i, j, max;	if(!f->busy)		return "read of unused fid";	n = rhdr.count;	off = rhdr.offset;	thdr.count = 0;	data = thdr.data;	switch(f->qtype){	case Qroot:		j = 0;		for(i = 0; i < Nuser; i++)			for(u = users[i]; u; j += m, u = u->link){				m = dostat(u, Quser, data, n);				if(m <= BIT16SZ)					break;				if(j < off)					continue;				data += m;				n -= m;			}		thdr.count = data - thdr.data;		return 0;	case Quser:		max = Qmax;		max -= Quser + 1;		j = 0;		for(i = 0; i < max; j += m, i++){			m = dostat(f->user, i + Quser + 1, data, n);			if(m <= BIT16SZ)				break;			if(j < off)				continue;			data += m;			n -= m;		}		thdr.count = data - thdr.data;		return 0;	case Qkey:		if(f->user->status != Sok)			return "user disabled";		if(f->user->purgatory > time(0))			return "user in purgatory";		if(f->user->expire != 0 && f->user->expire < time(0))			return "user expired";		if(off != 0)			return 0;		if(n > DESKEYLEN)			n = DESKEYLEN;		memmove(thdr.data, f->user->key, n);		thdr.count = n;		return 0;	case Qsecret:		if(f->user->status != Sok)			return "user disabled";		if(f->user->purgatory > time(0))			return "user in purgatory";		if(f->user->expire != 0 && f->user->expire < time(0))			return "user expired";		if(off != 0)			return 0;		if(n > strlen(f->user->secret))			n = strlen(f->user->secret);		memmove(thdr.data, f->user->secret, n);		thdr.count = n;		return 0;	case Qstatus:		if(off != 0){			thdr.count = 0;			return 0;		}		if(f->user->status == Sok && f->user->expire && f->user->expire < time(0))			sprint(thdr.data, "expired\n");		else			sprint(thdr.data, "%s\n", status[f->user->status]);		thdr.count = strlen(thdr.data);		return 0;	case Qexpire:		if(off != 0){			thdr.count = 0;			return 0;		}		if(!f->user->expire)			strcpy(data, "never\n");		else			sprint(data, "%lud\n", f->user->expire);		if(n > strlen(data))			n = strlen(data);		thdr.count = n;		return 0;	case Qlog:		if(off != 0){			thdr.count = 0;			return 0;		}		sprint(data, "%lud\n", f->user->bad);		if(n > strlen(data))			n = strlen(data);		thdr.count = n;		return 0;	case Qwarnings:		if(off != 0){			thdr.count = 0;			return 0;		}		sprint(data, "%ud\n", f->user->warnings);		if(n > strlen(data))			n = strlen(data);		thdr.count = n;		return 0;	default:		return "permission denied: unknown qid";	}}char *Write(Fid *f){	char *data, *p;	ulong n, expire;	int i;	if(!f->busy)		return "permission denied";	n = rhdr.count;	data = rhdr.data;	switch(f->qtype){	case Qkey:		if(n != DESKEYLEN)			return "garbled write data";		memmove(f->user->key, data, DESKEYLEN);		thdr.count = DESKEYLEN;		break;	case Qsecret:		if(n >= SECRETLEN)			return "garbled write data";		memmove(f->user->secret, data, n);		f->user->secret[n] = 0;		thdr.count = n;		break;	case Qstatus:		data[n] = '\0';		if(p = strchr(data, '\n'))			*p = '\0';		for(i = 0; i < Smax; i++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -