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

📄 p9cr.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * p9cr, vnc - textual challenge/response authentication * * Client protocol:	[currently unimplemented] *	write challenge *	read response * * Server protocol: *	write user *	read challenge * 	write response */#include "dat.h"enum{	Maxchal=	64,};typedef struct State State;struct State{	Key	*key;	int	astype;	int	asfd;	Ticket	t;	Ticketreq tr;	char	chal[Maxchal];	int	challen;	char	resp[Maxchal];	int	resplen;};enum{	CNeedChal,	CHaveResp,	SHaveChal,	SNeedResp,	Maxphase,};static char *phasenames[Maxphase] ={[CNeedChal]	"CNeedChal",[CHaveResp]	"CHaveResp",[SHaveChal]	"SHaveChal",[SNeedResp]	"SNeedResp",};static voidp9crclose(Fsstate *fss){	State *s;	s = fss->ps;	if(s->asfd >= 0){		close(s->asfd);		s->asfd = -1;	}	free(s);}static int getchal(State*, Fsstate*);static intp9crinit(Proto *p, Fsstate *fss){	int iscli, ret;	char *user;	State *s;	Attr *attr;	Keyinfo ki;	if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0)		return failure(fss, nil);		s = emalloc(sizeof(*s));	s->asfd = -1;	if(p == &p9cr){		s->astype = AuthChal;		s->challen = NETCHLEN;	}else if(p == &vnc){		s->astype = AuthVNC;		s->challen = Maxchal;	}else		abort();	if(iscli){		fss->phase = CNeedChal;		if(p == &p9cr)			attr = setattr(_copyattr(fss->attr), "proto=p9sk1");		else			attr = nil;		ret = findkey(&s->key, mkkeyinfo(&ki, fss, attr),			"role=client %s", p->keyprompt);		_freeattr(attr);		if(ret != RpcOk){			free(s);			return ret;		}		fss->ps = s;	}else{		if((ret = findp9authkey(&s->key, fss)) != RpcOk){			free(s);			return ret;		}		if((user = _strfindattr(fss->attr, "user")) == nil){			free(s);			return failure(fss, "no user name specified in start msg");		}		if(strlen(user) >= sizeof s->tr.uid){			free(s);			return failure(fss, "user name too long");		}		fss->ps = s;		strcpy(s->tr.uid, user);		ret = getchal(s, fss);		if(ret != RpcOk){			p9crclose(fss);	/* frees s */			fss->ps = nil;		}	}	fss->phasename = phasenames;	fss->maxphase = Maxphase;	return ret;}static intp9crread(Fsstate *fss, void *va, uint *n){	int m;	State *s;	s = fss->ps;	switch(fss->phase){	default:		return phaseerror(fss, "read");	case CHaveResp:		if(s->resplen < *n)			*n = s->resplen;		memmove(va, s->resp, *n);		fss->phase = Established;		return RpcOk;	case SHaveChal:		if(s->astype == AuthChal)			m = strlen(s->chal);	/* ascii string */		else			m = s->challen;		/* fixed length binary */		if(m > *n)			return toosmall(fss, m);		*n = m;		memmove(va, s->chal, m);		fss->phase = SNeedResp;		return RpcOk;	}}static intp9response(Fsstate *fss, State *s){	char key[DESKEYLEN];	uchar buf[8];	ulong chal;	char *pw;	pw = _strfindattr(s->key->privattr, "!password");	if(pw == nil)		return failure(fss, "vncresponse cannot happen");	passtokey(key, pw);	memset(buf, 0, 8);	sprint((char*)buf, "%d", atoi(s->chal));	if(encrypt(key, buf, 8) < 0)		return failure(fss, "can't encrypt response");	chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];	s->resplen = snprint(s->resp, sizeof s->resp, "%.8lux", chal);	return RpcOk;}static uchar tab[256];/* VNC reverses the bits of each byte before using as a des key */static voidmktab(void){	int i, j, k;	static int once;	if(once)		return;	once = 1;	for(i=0; i<256; i++) {		j=i;		tab[i] = 0;		for(k=0; k<8; k++) {			tab[i] = (tab[i]<<1) | (j&1);			j >>= 1;		}	}}static intvncaddkey(Key *k, int before){	uchar *p;	char *s;	k->priv = emalloc(8+1);	if(s = _strfindattr(k->privattr, "!password")){		mktab();		memset(k->priv, 0, 8+1);		strncpy((char*)k->priv, s, 8);		for(p=k->priv; *p; p++)			*p = tab[*p];	}else{		werrstr("no key data");		return -1;	}	return replacekey(k, before);}static voidvncclosekey(Key *k){	free(k->priv);}static intvncresponse(Fsstate*, State *s){	DESstate des;	memmove(s->resp, s->chal, sizeof s->chal);	setupDESstate(&des, s->key->priv, nil);	desECBencrypt((uchar*)s->resp, s->challen, &des);	s->resplen = s->challen;	return RpcOk;}static intp9crwrite(Fsstate *fss, void *va, uint n){	char tbuf[TICKETLEN+AUTHENTLEN];	State *s;	char *data = va;	Authenticator a;	char resp[Maxchal];	int ret;	s = fss->ps;	switch(fss->phase){	default:		return phaseerror(fss, "write");	case CNeedChal:		if(n >= sizeof(s->chal))			return failure(fss, Ebadarg);		memset(s->chal, 0, sizeof s->chal);		memmove(s->chal, data, n);		s->challen = n;		if(s->astype == AuthChal)			ret = p9response(fss, s);		else			ret = vncresponse(fss, s);		if(ret != RpcOk)			return ret;		fss->phase = CHaveResp;		return RpcOk;	case SNeedResp:		/* send response to auth server and get ticket */		if(n > sizeof(resp))			return failure(fss, Ebadarg);		memset(resp, 0, sizeof resp);		memmove(resp, data, n);		if(write(s->asfd, resp, s->challen) != s->challen)			return failure(fss, Easproto);		/* get ticket plus authenticator from auth server */		if(_asrdresp(s->asfd, tbuf, TICKETLEN+AUTHENTLEN) < 0)			return failure(fss, nil);		/* check ticket */		convM2T(tbuf, &s->t, s->key->priv);		if(s->t.num != AuthTs		|| memcmp(s->t.chal, s->tr.chal, sizeof(s->t.chal)) != 0){			disablekey(s->key);			return failure(fss, Easproto);		}		convM2A(tbuf+TICKETLEN, &a, s->t.key);		if(a.num != AuthAc		|| memcmp(a.chal, s->tr.chal, sizeof(a.chal)) != 0		|| a.id != 0)			return failure(fss, Easproto);		fss->haveai = 1;		fss->ai.cuid = s->t.cuid;		fss->ai.suid = s->t.suid;		fss->ai.nsecret = 0;		fss->ai.secret = nil;		fss->phase = Established;		return RpcOk;	}}static intgetchal(State *s, Fsstate *fss){	char trbuf[TICKREQLEN];	int n;	safecpy(s->tr.hostid, _strfindattr(s->key->attr, "user"), sizeof(s->tr.hostid));	safecpy(s->tr.authdom, _strfindattr(s->key->attr, "dom"), sizeof(s->tr.authdom));	s->tr.type = s->astype;	convTR2M(&s->tr, trbuf);	/* get challenge from auth server */	s->asfd = _authdial(nil, _strfindattr(s->key->attr, "dom"));	if(s->asfd < 0)		return failure(fss, Easproto);	if(write(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN)		return failure(fss, Easproto);	n = _asrdresp(s->asfd, s->chal, s->challen);	if(n <= 0){		if(n == 0)			werrstr("_asrdresp short read");		return failure(fss, nil);	}	s->challen = n;	fss->phase = SHaveChal;	return RpcOk;}Proto p9cr ={.name=		"p9cr",.init=		p9crinit,.write=		p9crwrite,.read=		p9crread,.close=		p9crclose,.keyprompt=	"user? !password?",};Proto vnc ={.name=		"vnc",.init=		p9crinit,.write=		p9crwrite,.read=		p9crread,.close=		p9crclose,.keyprompt=	"!password?",.addkey=	vncaddkey,};

⌨️ 快捷键说明

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