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

📄 chap.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * CHAP, MSCHAP *  * The client does not authenticate the server, hence no CAI * * Client protocol: *	write Chapchal  *	read response Chapreply or MSchaprely structure * * Server protocol: *	read challenge: 8 bytes binary *	write user: utf8 *	write response: Chapreply or MSchapreply structure */#include <ctype.h>#include "dat.h"enum {	ChapChallen = 8,	ChapResplen = 16,	MSchapResplen = 24,};static int dochal(State*);static int doreply(State*, void*, int);static void doLMchap(char *, uchar [ChapChallen], uchar [MSchapResplen]);static void doNTchap(char *, uchar [ChapChallen], uchar [MSchapResplen]);static void dochap(char *, int, char [ChapChallen], uchar [ChapResplen]);struct State{	char *protoname;	int astype;	int asfd;	Key *key;	Ticket	t;	Ticketreq	tr;	char chal[ChapChallen];	MSchapreply mcr;	char cr[ChapResplen];	char err[ERRMAX];	char user[64];	uchar secret[16];	/* for mschap */	int nsecret;};enum{	CNeedChal,	CHaveResp,	SHaveChal,	SNeedUser,	SNeedResp,	SHaveZero,	SHaveCAI,	Maxphase};static char *phasenames[Maxphase] ={[CNeedChal]	"CNeedChal",[CHaveResp]	"CHaveResp",[SHaveChal]	"SHaveChal",[SNeedUser]	"SNeedUser",[SNeedResp]	"SNeedResp",[SHaveZero]	"SHaveZero",[SHaveCAI]	"SHaveCAI",};static intchapinit(Proto *p, Fsstate *fss){	int iscli, ret;	State *s;	if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0)		return failure(fss, nil);	s = emalloc(sizeof *s);	fss->phasename = phasenames;	fss->maxphase = Maxphase;	s->asfd = -1;	if(p == &chap){		s->astype = AuthChap;		s->protoname = "chap";	}else{		s->astype = AuthMSchap;		s->protoname = "mschap";	}	if(iscli)		fss->phase = CNeedChal;	else{		if((ret = findp9authkey(&s->key, fss)) != RpcOk){			free(s);			return ret;		}		if(dochal(s) < 0){			free(s);			return failure(fss, nil);		}		fss->phase = SHaveChal;	}	fss->ps = s;	return RpcOk;}static voidchapclose(Fsstate *fss){	State *s;	s = fss->ps;	if(s->asfd >= 0){		close(s->asfd);		s->asfd = -1;	}	free(s);}static intchapwrite(Fsstate *fss, void *va, uint n){	int ret, nreply;	char *a, *v;	void *reply;	Key *k;	Keyinfo ki;	State *s;	Chapreply cr;	MSchapreply mcr;	OChapreply ocr;	OMSchapreply omcr;	s = fss->ps;	a = va;	switch(fss->phase){	default:		return phaseerror(fss, "write");	case CNeedChal:		ret = findkey(&k, mkkeyinfo(&ki, fss, nil), "%s", fss->proto->keyprompt);		if(ret != RpcOk)			return ret;		v = _strfindattr(k->privattr, "!password");		if(v == nil)			return failure(fss, "key has no password");		setattrs(fss->attr, k->attr);		switch(s->astype){		default:			abort();		case AuthMSchap:			doLMchap(v, (uchar *)a, (uchar *)s->mcr.LMresp);			doNTchap(v, (uchar *)a, (uchar *)s->mcr.NTresp);			break;		case AuthChap:			dochap(v, *a, a+1, (uchar *)s->cr);			break;		}		closekey(k);		fss->phase = CHaveResp;		return RpcOk;	case SNeedUser:		if(n >= sizeof s->user)			return failure(fss, "user name too long");		memmove(s->user, va, n);		s->user[n] = '\0';		fss->phase = SNeedResp;		return RpcOk;	case SNeedResp:		switch(s->astype){		default:			return failure(fss, "chap internal botch");		case AuthChap:			if(n != sizeof(Chapreply))				return failure(fss, "did not get Chapreply");			memmove(&cr, va, sizeof cr);			ocr.id = cr.id;			memmove(ocr.resp, cr.resp, sizeof ocr.resp);			memset(omcr.uid, 0, sizeof(omcr.uid));			strecpy(ocr.uid, ocr.uid+sizeof ocr.uid, s->user);			reply = &ocr;			nreply = sizeof ocr;			break;		case AuthMSchap:			if(n != sizeof(MSchapreply))				return failure(fss, "did not get MSchapreply");			memmove(&mcr, va, sizeof mcr);			memmove(omcr.LMresp, mcr.LMresp, sizeof omcr.LMresp);			memmove(omcr.NTresp, mcr.NTresp, sizeof omcr.NTresp);			memset(omcr.uid, 0, sizeof(omcr.uid));			strecpy(omcr.uid, omcr.uid+sizeof omcr.uid, s->user);			reply = &omcr;			nreply = sizeof omcr;			break;		}		if(doreply(s, reply, nreply) < 0)			return failure(fss, nil);		fss->phase = Established;		fss->ai.cuid = s->t.cuid;		fss->ai.suid = s->t.suid;		fss->ai.secret = s->secret;		fss->ai.nsecret = s->nsecret;		fss->haveai = 1;		return RpcOk;	}}static intchapread(Fsstate *fss, void *va, uint *n){	State *s;	s = fss->ps;	switch(fss->phase){	default:		return phaseerror(fss, "read");	case CHaveResp:		switch(s->astype){		default:			phaseerror(fss, "write");			break;		case AuthMSchap:			if(*n > sizeof(MSchapreply))				*n = sizeof(MSchapreply);			memmove(va, &s->mcr, *n);			break;		case AuthChap:			if(*n > ChapResplen)				*n = ChapResplen;			memmove(va, s->cr, ChapResplen);			break;		}		fss->phase = Established;		fss->haveai = 0;		return RpcOk;	case SHaveChal:		if(*n > sizeof s->chal)			*n = sizeof s->chal;		memmove(va, s->chal, *n);		fss->phase = SNeedUser;		return RpcOk;	}}static intdochal(State *s){	char *dom, *user;	char trbuf[TICKREQLEN];	s->asfd = -1;	/* send request to authentication server and get challenge */	if((dom = _strfindattr(s->key->attr, "dom")) == nil	|| (user = _strfindattr(s->key->attr, "user")) == nil){		werrstr("chap/dochal cannot happen");		goto err;	}	s->asfd = _authdial(nil, dom);	if(s->asfd < 0)		goto err;		memset(&s->tr, 0, sizeof(s->tr));	s->tr.type = s->astype;	safecpy(s->tr.authdom, dom, sizeof s->tr.authdom);	safecpy(s->tr.hostid, user, sizeof(s->tr.hostid));	convTR2M(&s->tr, trbuf);	if(write(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN)		goto err;	/* readn, not _asrdresp.  needs to match auth.srv.c. */	if(readn(s->asfd, s->chal, sizeof s->chal) != sizeof s->chal)		goto err;	return 0;err:	if(s->asfd >= 0)		close(s->asfd);	s->asfd = -1;	return -1;}static intdoreply(State *s, void *reply, int nreply){	char ticket[TICKETLEN+AUTHENTLEN];	int n;	Authenticator a;	if((n=write(s->asfd, reply, nreply)) != nreply){		if(n >= 0)			werrstr("short write to auth server");		goto err;	}	if(_asrdresp(s->asfd, ticket, TICKETLEN+AUTHENTLEN) < 0){		/* leave connection open so we can try again */		return -1;	}	s->nsecret = readn(s->asfd, s->secret, sizeof s->secret);	if(s->nsecret < 0)		s->nsecret = 0;	close(s->asfd);	s->asfd = -1;	convM2T(ticket, &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);		werrstr(Easproto);		return -1;	}	convM2A(ticket+TICKETLEN, &a, s->t.key);	if(a.num != AuthAc	|| memcmp(a.chal, s->tr.chal, sizeof(a.chal)) != 0	|| a.id != 0){		werrstr(Easproto);		return -1;	}	return 0;err:	if(s->asfd >= 0)		close(s->asfd);	s->asfd = -1;	return -1;}Proto chap = {.name=	"chap",.init=	chapinit,.write=	chapwrite,.read=	chapread,.close=	chapclose,.addkey= replacekey,.keyprompt= "!password?"};Proto mschap = {.name=	"mschap",.init=	chapinit,.write=	chapwrite,.read=	chapread,.close=	chapclose,.addkey= replacekey,.keyprompt= "!password?"};static voidhash(uchar pass[16], uchar c8[ChapChallen], uchar p24[MSchapResplen]){	int i;	uchar p21[21];	ulong schedule[32];	memset(p21, 0, sizeof p21 );	memmove(p21, pass, 16);	for(i=0; i<3; i++) {		key_setup(p21+i*7, schedule);		memmove(p24+i*8, c8, 8);		block_cipher(schedule, p24+i*8, 0);	}}static voiddoNTchap(char *pass, uchar chal[ChapChallen], uchar reply[MSchapResplen]){	Rune r;	int i, n;	uchar digest[MD4dlen];	uchar *w, unipass[256];	// Standard says unlimited length, experience says 128 max	if ((n = strlen(pass)) > 128)		n = 128;	for(i=0, w=unipass; i < n; i++) {		pass += chartorune(&r, pass);		*w++ = r & 0xff;		*w++ = r >> 8;	}	memset(digest, 0, sizeof digest);	md4(unipass, w-unipass, digest, nil);	memset(unipass, 0, sizeof unipass);	hash(digest, chal, reply);}static voiddoLMchap(char *pass, uchar chal[ChapChallen], uchar reply[MSchapResplen]){	int i;	ulong schedule[32];	uchar p14[15], p16[16];	uchar s8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};	int n = strlen(pass);	if(n > 14){		// let prudent people avoid the LM vulnerability		//   and protect the loop below from buffer overflow		memset(reply, 0, MSchapResplen);		return;	}	// Spec says space padded, experience says otherwise	memset(p14, 0, sizeof p14 -1);	p14[sizeof p14 - 1] = '\0';	// NT4 requires uppercase, Win XP doesn't care	for (i = 0; pass[i]; i++)		p14[i] = islower(pass[i])? toupper(pass[i]): pass[i];	for(i=0; i<2; i++) {		key_setup(p14+i*7, schedule);		memmove(p16+i*8, s8, 8);		block_cipher(schedule, p16+i*8, 0);	}	memset(p14, 0, sizeof p14);	hash(p16, chal, reply);}static voiddochap(char *pass, int id, char chal[ChapChallen], uchar resp[ChapResplen]){	char buf[1+ChapChallen+MAXNAMELEN+1];	int n = strlen(pass);	*buf = id;	if (n > MAXNAMELEN)		n = MAXNAMELEN-1;	memset(buf, 0, sizeof buf);	strncpy(buf+1, pass, n);	memmove(buf+1+n, chal, ChapChallen);	md5((uchar*)buf, 1+n+ChapChallen, resp, nil);}

⌨️ 快捷键说明

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