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

📄 authsrv.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <ndb.h>#include <regexp.h>#include <mp.h>#include <libsec.h>#include <authsrv.h>#include "authcmdlib.h"int debug;Ndb *db;char raddr[128];/* Microsoft auth constants */enum {	MShashlen = 16,	MSchallen = 8,	MSresplen = 24,};int	ticketrequest(Ticketreq*);void	challengebox(Ticketreq*);void	changepasswd(Ticketreq*);void	apop(Ticketreq*, int);void	chap(Ticketreq*);void	mschap(Ticketreq*);void	http(Ticketreq*);void	vnc(Ticketreq*);int	speaksfor(char*, char*);void	replyerror(char*, ...);void	getraddr(char*);void	mkkey(char*);void	randombytes(uchar*, int);void	nthash(uchar hash[MShashlen], char *passwd);void	lmhash(uchar hash[MShashlen], char *passwd);void	mschalresp(uchar resp[MSresplen], uchar hash[MShashlen], uchar chal[MSchallen]);void	desencrypt(uchar data[8], uchar key[7]);int	tickauthreply(Ticketreq*, char*);void	safecpy(char*, char*, int);voidmain(int argc, char *argv[]){	char buf[TICKREQLEN];	Ticketreq tr;	ARGBEGIN{	case 'd':		debug++;	}ARGEND	strcpy(raddr, "unknown");	if(argc >= 1)		getraddr(argv[argc-1]);	alarm(10*60*1000);	/* kill a connection after 10 minutes */	db = ndbopen("/lib/ndb/auth");	if(db == 0)		syslog(0, AUTHLOG, "no /lib/ndb/auth");	srand(time(0)*getpid());	for(;;){		if(readn(0, buf, TICKREQLEN) <= 0)			exits(0);			convM2TR(buf, &tr);		switch(buf[0]){		case AuthTreq:			ticketrequest(&tr);			break;		case AuthChal:			challengebox(&tr);			break;		case AuthPass:			changepasswd(&tr);			break;		case AuthApop:			apop(&tr, AuthApop);			break;		case AuthChap:			chap(&tr);			break;		case AuthMSchap:			mschap(&tr);			break;		case AuthCram:			apop(&tr, AuthCram);			break;		case AuthHttp:			http(&tr);			break;		case AuthVNC:			vnc(&tr);			break;		default:			syslog(0, AUTHLOG, "unknown ticket request type: %d", buf[0]);			exits(0);		}	}	/* not reached */}intticketrequest(Ticketreq *tr){	char akey[DESKEYLEN];	char hkey[DESKEYLEN];	Ticket t;	char tbuf[2*TICKETLEN+1];	if(findkey(KEYDB, tr->authid, akey) == 0){		/* make one up so caller doesn't know it was wrong */		mkkey(akey);		if(debug)			syslog(0, AUTHLOG, "tr-fail authid %s", raddr);	}	if(findkey(KEYDB, tr->hostid, hkey) == 0){		/* make one up so caller doesn't know it was wrong */		mkkey(hkey);		if(debug)			syslog(0, AUTHLOG, "tr-fail hostid %s(%s)", tr->hostid, raddr);	}	memset(&t, 0, sizeof(t));	memmove(t.chal, tr->chal, CHALLEN);	strcpy(t.cuid, tr->uid);	if(speaksfor(tr->hostid, tr->uid))		strcpy(t.suid, tr->uid);	else {		mkkey(akey);		mkkey(hkey);		if(debug)			syslog(0, AUTHLOG, "tr-fail %s@%s(%s) -> %s@%s no speaks for",				tr->uid, tr->hostid, raddr, tr->uid, tr->authid);	}	mkkey(t.key);	tbuf[0] = AuthOK;	t.num = AuthTc;	convT2M(&t, tbuf+1, hkey);	t.num = AuthTs;	convT2M(&t, tbuf+1+TICKETLEN, akey);	if(write(1, tbuf, 2*TICKETLEN+1) < 0){		if(debug)			syslog(0, AUTHLOG, "tr-fail %s@%s(%s): hangup",				tr->uid, tr->hostid, raddr);		exits(0);	}	if(debug)		syslog(0, AUTHLOG, "tr-ok %s@%s(%s) -> %s@%s",			tr->uid, tr->hostid, raddr, tr->uid, tr->authid);	return 0;}voidchallengebox(Ticketreq *tr){	long chal;	char *key, *netkey;	char kbuf[DESKEYLEN], nkbuf[DESKEYLEN], hkey[DESKEYLEN];	char buf[NETCHLEN+1];	char *err;	key = findkey(KEYDB, tr->uid, kbuf);	netkey = findkey(NETKEYDB, tr->uid, nkbuf);	if(key == 0 && netkey == 0){		/* make one up so caller doesn't know it was wrong */		mkkey(nkbuf);		netkey = nkbuf;		if(debug)			syslog(0, AUTHLOG, "cr-fail uid %s@%s", tr->uid, raddr);	}	if(findkey(KEYDB, tr->hostid, hkey) == 0){		/* make one up so caller doesn't know it was wrong */		mkkey(hkey);		if(debug)			syslog(0, AUTHLOG, "cr-fail hostid %s %s@%s", tr->hostid,				tr->uid, raddr);	}	/*	 * challenge-response	 */	memset(buf, 0, sizeof(buf));	buf[0] = AuthOK;	chal = lnrand(MAXNETCHAL);	sprint(buf+1, "%lud", chal);	if(write(1, buf, NETCHLEN+1) < 0)		exits(0);	if(readn(0, buf, NETCHLEN) < 0)		exits(0);	if(!(key && netcheck(key, chal, buf))	&& !(netkey && netcheck(netkey, chal, buf))	&& (err = secureidcheck(tr->uid, buf)) != nil){		replyerror("cr-fail %s %s %s", err, tr->uid, raddr);		logfail(tr->uid);		if(debug)			syslog(0, AUTHLOG, "cr-fail %s@%s(%s): bad resp",				tr->uid, tr->hostid, raddr);		return;	}	succeed(tr->uid);	/*	 *  reply with ticket & authenticator	 */	if(tickauthreply(tr, hkey) < 0){		if(debug)			syslog(0, AUTHLOG, "cr-fail %s@%s(%s): hangup",				tr->uid, tr->hostid, raddr);		exits(0);	}	if(debug)		syslog(0, AUTHLOG, "cr-ok %s@%s(%s)",			tr->uid, tr->hostid, raddr);}voidchangepasswd(Ticketreq *tr){	Ticket t;	char tbuf[TICKETLEN+1];	char prbuf[PASSREQLEN];	Passwordreq pr;	char okey[DESKEYLEN], nkey[DESKEYLEN];	char *err;	if(findkey(KEYDB, tr->uid, okey) == 0){		/* make one up so caller doesn't know it was wrong */		mkkey(okey);		syslog(0, AUTHLOG, "cp-fail uid %s", raddr);	}	/* send back a ticket with a new key */	memmove(t.chal, tr->chal, CHALLEN);	mkkey(t.key);	tbuf[0] = AuthOK;	t.num = AuthTp;	safecpy(t.cuid, tr->uid, sizeof(t.cuid));	safecpy(t.suid, tr->uid, sizeof(t.suid));	convT2M(&t, tbuf+1, okey);	write(1, tbuf, sizeof(tbuf));			/* loop trying passwords out */	for(;;){		if(readn(0, prbuf, PASSREQLEN) < 0)			exits(0);		convM2PR(prbuf, &pr, t.key);		if(pr.num != AuthPass){			replyerror("protocol botch1: %s", raddr);			exits(0);		}		passtokey(nkey, pr.old);		if(memcmp(nkey, okey, DESKEYLEN)){			replyerror("protocol botch2: %s", raddr);			continue;		}		if(*pr.new){			err = okpasswd(pr.new);			if(err){				replyerror("%s %s", err, raddr);				continue;			}			passtokey(nkey, pr.new);		}		if(pr.changesecret && setsecret(KEYDB, tr->uid, pr.secret) == 0){			replyerror("can't write secret %s", raddr);			continue;		}		if(*pr.new && setkey(KEYDB, tr->uid, nkey) == 0){			replyerror("can't write key %s", raddr);			continue;		}		break;	}	prbuf[0] = AuthOK;	write(1, prbuf, 1);	succeed(tr->uid);	return;}voidhttp(Ticketreq *tr){	Ticket t;	char tbuf[TICKETLEN+1];	char key[DESKEYLEN];	char *p;	Biobuf *b;	int n;	n = strlen(tr->uid);	b = Bopen("/sys/lib/httppasswords", OREAD);	if(b == nil){		replyerror("no password file", raddr);		return;	}	/* find key */	for(;;){		p = Brdline(b, '\n');		if(p == nil)			break;		p[Blinelen(b)-1] = 0;		if(strncmp(p, tr->uid, n) == 0)		if(p[n] == ' ' || p[n] == '\t'){			p += n;			break;		}	}	Bterm(b);	if(p == nil) {		randombytes((uchar*)key, DESKEYLEN);	} else {		while(*p == ' ' || *p == '\t')			p++;		passtokey(key, p);	}		/* send back a ticket encrypted with the key */	randombytes((uchar*)t.chal, CHALLEN);	mkkey(t.key);	tbuf[0] = AuthOK;	t.num = AuthHr;	safecpy(t.cuid, tr->uid, sizeof(t.cuid));	safecpy(t.suid, tr->uid, sizeof(t.suid));	convT2M(&t, tbuf+1, key);	write(1, tbuf, sizeof(tbuf));}static char*domainname(void){	static char sysname[Maxpath];	static char *domain;	int n;	if(domain)		return domain;	if(*sysname)		return sysname;	domain = csgetvalue(0, "sys", sysname, "dom", nil);	if(domain)		return domain;	n = readfile("/dev/sysname", sysname, sizeof(sysname)-1);	if(n < 0){		strcpy(sysname, "kremvax");		return sysname;	}	sysname[n] = 0;	return sysname;}static inth2b(char c){	if(c >= '0' && c <= '9')		return c - '0';	if(c >= 'A' && c <= 'F')		return c - 'A' + 10;	if(c >= 'a' && c <= 'f')		return c - 'a' + 10;	return 0;}voidapop(Ticketreq *tr, int type){	int challen, i, tries;	char *secret, *hkey, *p;	Ticketreq treq;	DigestState *s;	char sbuf[SECRETLEN], hbuf[DESKEYLEN];	char tbuf[TICKREQLEN];	char buf[MD5dlen*2];	uchar digest[MD5dlen], resp[MD5dlen];	ulong rb[4];	char chal[256];	USED(tr);	/*	 *  Create a challenge and send it.  	 */	randombytes((uchar*)rb, sizeof(rb));	p = chal;	p += snprint(p, sizeof(chal), "<%lux%lux.%lux%lux@%s>",		rb[0], rb[1], rb[2], rb[3], domainname());	challen = p - chal;	print("%c%-5d%s", AuthOKvar, challen, chal);	/* give user a few attempts */	for(tries = 0; ; tries++) {		/*		 *  get ticket request		 */		if(readn(0, tbuf, TICKREQLEN) < 0)			exits(0);		convM2TR(tbuf, &treq);		tr = &treq;		if(tr->type != type)			exits(0);			/*		 * read response		 */		if(readn(0, buf, MD5dlen*2) < 0)			exits(0);		for(i = 0; i < MD5dlen; i++)			resp[i] = (h2b(buf[2*i])<<4)|h2b(buf[2*i+1]);			/*		 * lookup		 */		secret = findsecret(KEYDB, tr->uid, sbuf);		hkey = findkey(KEYDB, tr->hostid, hbuf);		if(hkey == 0 || secret == 0){			replyerror("apop-fail bad response %s", raddr);			logfail(tr->uid);			if(tries > 5)				return;			continue;		}			/*		 *  check for match		 */		if(type == AuthCram){			hmac_md5((uchar*)chal, challen,				(uchar*)secret, strlen(secret),				digest, nil);		} else {			s = md5((uchar*)chal, challen, 0, 0);			md5((uchar*)secret, strlen(secret), digest, s);		}		if(memcmp(digest, resp, MD5dlen) != 0){			replyerror("apop-fail bad response %s", raddr);			logfail(tr->uid);			if(tries > 5)				return;

⌨️ 快捷键说明

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