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

📄 secstore.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* network login client */#include <u.h>#include <libc.h>#include <mp.h>#include <libsec.h>#include <authsrv.h>#include "SConn.h"#include "secstore.h"enum{ CHK = 16, MAXFILES = 100 };typedef struct AuthConn{	SConn *conn;	char pass[64];	int passlen;} AuthConn;int verbose;Nvrsafe nvr;voidusage(void){	fprint(2, "usage: secstore [-cin] [-g getfile] [-p putfile] [-r rmfile] [-s tcp!server!5356] [-u user] [-v]\n");	exits("usage");}static intgetfile(SConn *conn, char *gf, uchar **buf, ulong *buflen, uchar *key, int nkey){	int fd = -1;	int i, n, nr, nw, len;	char s[Maxmsg+1];	uchar skey[SHA1dlen], ib[Maxmsg+CHK], *ibr, *ibw, *bufw, *bufe;	AESstate aes;	DigestState *sha;	if(strchr(gf, '/')){		fprint(2, "secstore: simple filenames, not paths like %s\n", gf);		return -1;	}	memset(&aes, 0, sizeof aes);	snprint(s, Maxmsg, "GET %s\n", gf);	conn->write(conn, (uchar*)s, strlen(s));	/* get file size */	s[0] = '\0';	bufw = bufe = nil;	if(readstr(conn, s) < 0){		fprint(2, "secstore: remote: %s\n", s);		return -1;	}	len = atoi(s);	if(len == -1){		fprint(2, "secstore: remote file %s does not exist\n", gf);		return -1;	}else if(len == -3){		fprint(2, "secstore: implausible filesize for %s\n", gf);		return -1;	}else if(len < 0){		fprint(2, "secstore: GET refused for %s\n", gf);		return -1;	}	if(buf != nil){		*buflen = len - AESbsize - CHK;		*buf = bufw = emalloc(len);		bufe = bufw + len;	}	/* directory listing */	if(strcmp(gf,".")==0){		if(buf != nil)			*buflen = len;		for(i=0; i < len; i += n){			if((n = conn->read(conn, (uchar*)s, Maxmsg)) <= 0){				fprint(2, "secstore: empty file chunk\n");				return -1;			}			if(buf == nil)				write(1, s, n);			else				memmove((*buf)+i, s, n);		}		return 0;	}	/* conn is already encrypted against wiretappers, 		but gf is also encrypted against server breakin. */	if(buf == nil && (fd =create(gf, OWRITE, 0600)) < 0){		fprint(2, "secstore: can't open %s: %r\n", gf);		return -1;	}	ibr = ibw = ib;	for(nr=0; nr < len;){		if((n = conn->read(conn, ibw, Maxmsg)) <= 0){			fprint(2, "secstore: empty file chunk n=%d nr=%d len=%d: %r\n",				n, nr, len);			return -1;		}		nr += n;		ibw += n;		if(!aes.setup){ /* first time, read 16 byte IV */			if(n < AESbsize){				fprint(2, "secstore: no IV in file\n");				return -1;			}			sha = sha1((uchar*)"aescbc file", 11, nil, nil);			sha1(key, nkey, skey, sha);			setupAESstate(&aes, skey, AESbsize, ibr);			memset(skey, 0, sizeof skey);			ibr += AESbsize;			n -= AESbsize;		}		aesCBCdecrypt(ibw-n, n, &aes);		n = ibw-ibr-CHK;		if(n > 0){			if(buf == nil){				nw = write(fd, ibr, n);				if(nw != n){					fprint(2, "secstore: write error on %s", gf);					return -1;				}			}else{				assert(bufw+n <= bufe);				memmove(bufw, ibr, n);				bufw += n;			}			ibr += n;		}		memmove(ib, ibr, ibw-ibr);		ibw = ib + (ibw-ibr);		ibr = ib;	}	if(buf == nil)		close(fd);	n = ibw-ibr;	if((n != CHK) || (memcmp(ib, "XXXXXXXXXXXXXXXX", CHK) != 0)){		fprint(2, "secstore: decrypted file failed to authenticate!\n");		return -1;	}	return 0;}// This sends a file to the secstore disk that can, in an emergency, be// decrypted by the program aescbc.c.static intputfile(SConn *conn, char *pf, uchar *buf, ulong len, uchar *key, int nkey){	int i, n, fd, ivo, bufi, done;	char s[Maxmsg];	uchar  skey[SHA1dlen], b[CHK+Maxmsg], IV[AESbsize];	AESstate aes;	DigestState *sha;	/* create initialization vector */	srand(time(0));  /* doesn't need to be unpredictable */	for(i=0; i<AESbsize; i++)		IV[i] = 0xff & rand();	sha = sha1((uchar*)"aescbc file", 11, nil, nil);	sha1(key, nkey, skey, sha);	setupAESstate(&aes, skey, AESbsize, IV);	memset(skey, 0, sizeof skey);	snprint(s, Maxmsg, "PUT %s\n", pf);	conn->write(conn, (uchar*)s, strlen(s));	if(buf == nil){		/* get file size */		if((fd = open(pf, OREAD)) < 0){			fprint(2, "secstore: can't open %s: %r\n", pf);			return -1;		}		len = seek(fd, 0, 2);		seek(fd, 0, 0);	} else {		fd = -1;	}	if(len > MAXFILESIZE){		fprint(2, "secstore: implausible filesize %ld for %s\n",			len, pf);		return -1;	}	/* send file size */	snprint(s, Maxmsg, "%ld", len+AESbsize+CHK);	conn->write(conn, (uchar*)s, strlen(s));	/* send IV and file+XXXXX in Maxmsg chunks */	ivo = AESbsize;	bufi = 0;	memcpy(b, IV, ivo);	for(done = 0; !done; ){		if(buf == nil){			n = read(fd, b+ivo, Maxmsg-ivo);			if(n < 0){				fprint(2, "secstore: read error on %s: %r\n",					pf);				return -1;			}		}else{			if((n = len - bufi) > Maxmsg-ivo)					n = Maxmsg-ivo;			memcpy(b+ivo, buf+bufi, n);			bufi += n;		}		n += ivo;		ivo = 0;		if(n < Maxmsg){ /* EOF on input; append XX... */			memset(b+n, 'X', CHK);			n += CHK; // might push n>Maxmsg			done = 1;		}		aesCBCencrypt(b, n, &aes);		if(n > Maxmsg){			assert(done==1);			conn->write(conn, b, Maxmsg);			n -= Maxmsg;			memmove(b, b+Maxmsg, n);		}		conn->write(conn, b, n);	}	if(buf == nil)		close(fd);	fprint(2, "secstore: saved %ld bytes\n", len);	return 0;}static intremovefile(SConn *conn, char *rf){	char buf[Maxmsg];	if(strchr(rf, '/')){		fprint(2, "secstore: simple filenames, not paths like %s\n", rf);		return -1;	}	snprint(buf, Maxmsg, "RM %s\n", rf);	conn->write(conn, (uchar*)buf, strlen(buf));	return 0;}static intcmd(AuthConn *c, char **gf, int *Gflag, char **pf, char **rf){	ulong len;	int rv = -1;	uchar *memfile, *memcur, *memnext;	while(*gf != nil){		if(verbose)			fprint(2, "get %s\n", *gf);		if(getfile(c->conn, *gf, *Gflag ? &memfile : nil, &len, (uchar*)c->pass, c->passlen) < 0)			goto Out;		if(*Gflag){			// write one line at a time, as required by /mnt/factotum/ctl			memcur = memfile;			while(len>0){				memnext = (uchar*)strchr((char*)memcur, '\n');				if(memnext){					write(1, memcur, memnext-memcur+1);					len -= memnext-memcur+1;					memcur = memnext+1;				}else{					write(1, memcur, len);					break;				}			}			free(memfile);		}		gf++;		Gflag++;	}	while(*pf != nil){		if(verbose)			fprint(2, "put %s\n", *pf);		if(putfile(c->conn, *pf, nil, 0, (uchar*)c->pass, c->passlen) < 0)			goto Out;		pf++;	}	while(*rf != nil){		if(verbose)			fprint(2, "rm  %s\n", *rf);		if(removefile(c->conn, *rf) < 0)			goto Out;		rf++;	}	c->conn->write(c->conn, (uchar*)"BYE", 3);	rv = 0;Out:	c->conn->free(c->conn);	return rv;}static intchpasswd(AuthConn *c, char *id){	ulong len;	int rv = -1, newpasslen = 0;	mpint *H, *Hi;	uchar *memfile;	char *newpass, *passck;	char *list, *cur, *next, *hexHi;	char *f[8], prompt[128];	H = mpnew(0);	Hi = mpnew(0);	// changing our password is vulnerable to connection failure	for(;;){		snprint(prompt, sizeof(prompt), "new password for %s: ", id);		newpass = getpassm(prompt);		if(newpass == nil)			goto Out;		if(strlen(newpass) >= 7)			break;		else if(strlen(newpass) == 0){			fprint(2, "!password change aborted\n");			goto Out;		}		print("!password must be at least 7 characters\n");	}	newpasslen = strlen(newpass);	snprint(prompt, sizeof(prompt), "retype password: ");	passck = getpassm(prompt);	if(passck == nil){		fprint(2, "secstore: getpassm failed\n");		goto Out;	}	if(strcmp(passck, newpass) != 0){		fprint(2, "secstore: passwords didn't match\n");		goto Out;	}	c->conn->write(c->conn, (uchar*)"CHPASS", strlen("CHPASS"));	hexHi = PAK_Hi(id, newpass, H, Hi);	c->conn->write(c->conn, (uchar*)hexHi, strlen(hexHi));	free(hexHi);	mpfree(H);	mpfree(Hi);	if(getfile(c->conn, ".", (uchar **) &list, &len, nil, 0) < 0){		fprint(2, "secstore: directory listing failed.\n");		goto Out;	}	/* Loop over files and reencrypt them; try to keep going after error */	for(cur=list; (next=strchr(cur, '\n')) != nil; cur=next+1){		*next = '\0';		if(tokenize(cur, f, nelem(f))< 1)			break;		fprint(2, "secstore: reencrypting '%s'\n", f[0]);		if(getfile(c->conn, f[0], &memfile, &len, (uchar*)c->pass, c->passlen) < 0){			fprint(2, "secstore: getfile of '%s' failed\n", f[0]);			continue;		}		if(putfile(c->conn, f[0], memfile, len, (uchar*)newpass, newpasslen) < 0)			fprint(2, "secstore: putfile of '%s' failed\n", f[0]);		free(memfile);	}	free(list);	c->conn->write(c->conn, (uchar*)"BYE", 3);	rv = 0;Out:	if(newpass != nil){		memset(newpass, 0, newpasslen);		free(newpass);	}	c->conn->free(c->conn);	return rv;}static AuthConn*login(char *id, char *dest, int pass_stdin, int pass_nvram){	AuthConn *c;	int fd, n, ntry = 0;	char *S, *PINSTA = nil, *nl, s[Maxmsg+1], *pass;	if(dest == nil)		sysfatal("tried to login with nil dest");	c = emalloc(sizeof(*c));	if(pass_nvram){		if(readnvram(&nvr, 0) < 0)			exits("readnvram: %r");		strecpy(c->pass, c->pass+sizeof c->pass, nvr.config);	}	if(pass_stdin){		n = readn(0, s, Maxmsg-2);  // so len(PINSTA)<Maxmsg-3		if(n < 1)			exits("no password on standard input");		s[n] = 0;		nl = strchr(s, '\n');		if(nl){			*nl++ = 0;			PINSTA = estrdup(nl);			nl = strchr(PINSTA, '\n');			if(nl)				*nl = 0;		}		strecpy(c->pass, c->pass+sizeof c->pass, s);	}	for(;;){		if(verbose)			fprint(2, "dialing %s\n", dest);		if((fd = dial(dest, nil, nil, nil)) < 0){			fprint(2, "secstore: can't dial %s\n", dest);			free(c);			return nil;		}		if((c->conn = newSConn(fd)) == nil){			free(c);			return nil;		}		ntry++;		if(!pass_stdin && !pass_nvram){			pass = getpassm("secstore password: ");			if(strlen(pass) >= sizeof c->pass){				fprint(2, "secstore: password too long, skipping secstore login\n");				exits("password too long");			}			strcpy(c->pass, pass);			memset(pass, 0, strlen(pass));			free(pass);		}		if(c->pass[0]==0){			fprint(2, "secstore: null password, skipping secstore login\n");			exits("no password");		}		if(PAKclient(c->conn, id, c->pass, &S) >= 0)			break;		c->conn->free(c->conn);		if(pass_stdin)			exits("invalid password on standard input");		if(pass_nvram)			exits("invalid password in nvram");		// and let user try retyping the password		if(ntry==3)			fprint(2, "Enter an empty password to quit.\n");	}	c->passlen = strlen(c->pass);	fprint(2, "%s\n", S);	free(S);	if(readstr(c->conn, s) < 0){		c->conn->free(c->conn);		free(c);		return nil;	}	if(strcmp(s, "STA") == 0){		long sn;		if(pass_stdin){			if(PINSTA)				strncpy(s+3, PINSTA, (sizeof s)-3);			else				exits("missing PIN+SecureID on standard input");			free(PINSTA);		}else{			pass = getpassm("STA PIN+SecureID: ");			strncpy(s+3, pass, (sizeof s)-4);			memset(pass, 0, strlen(pass));			free(pass);		}		sn = strlen(s+3);		if(verbose)			fprint(2, "%ld\n", sn);		c->conn->write(c->conn, (uchar*)s, sn+3);		readstr(c->conn, s);	}	if(strcmp(s, "OK") != 0){		fprint(2, "%s\n", s);		c->conn->free(c->conn);		free(c);		return nil;	}	return c;}intmain(int argc, char **argv){	int chpass = 0, pass_stdin = 0, pass_nvram = 0, rc;	int ngfile = 0, npfile = 0, nrfile = 0, Gflag[MAXFILES+1];	char *gfile[MAXFILES], *pfile[MAXFILES], *rfile[MAXFILES];	char *serve, *tcpserve, *user;	AuthConn *c;	serve = "$auth";	user = getuser();	memset(Gflag, 0, sizeof Gflag);	ARGBEGIN{	case 'c':		chpass = 1;		break;	case 'G':		Gflag[ngfile]++;		/* fall through */	case 'g':		if(ngfile >= MAXFILES)			exits("too many gfiles");		gfile[ngfile++] = ARGF();		if(gfile[ngfile-1] == nil)			usage();		break;	case 'i':		pass_stdin = 1;		break;	case 'n':		pass_nvram = 1;		break;	case 'p':		if(npfile >= MAXFILES)			exits("too many pfiles");		pfile[npfile++] = ARGF();		if(pfile[npfile-1] == nil)			usage();		break;	case 'r':		if(nrfile >= MAXFILES)			exits("too many rfiles");		rfile[nrfile++] = ARGF();		if(rfile[nrfile-1] == nil)			usage();		break;	case 's':		serve = EARGF(usage());		break;	case 'u':		user = EARGF(usage());		break;	case 'v':		verbose++;		break;	default:		usage();		break;	}ARGEND;	gfile[ngfile] = nil;	pfile[npfile] = nil;	rfile[nrfile] = nil;	if(argc!=0 || user==nil)		usage();	if(chpass && (ngfile || npfile || nrfile)){		fprint(2, "secstore: Get, put, and remove invalid with password change.\n");		exits("usage");	}	rc = strlen(serve)+sizeof("tcp!!99990");	tcpserve = emalloc(rc);	if(strchr(serve,'!'))		strcpy(tcpserve, serve);	else		snprint(tcpserve, rc, "tcp!%s!5356", serve);	c = login(user, tcpserve, pass_stdin, pass_nvram);	free(tcpserve);	if(c == nil)		sysfatal("secstore authentication failed");	if(chpass)		rc = chpasswd(c, user);	else		rc = cmd(c, gfile, Gflag, pfile, rfile);	if(rc < 0)		sysfatal("secstore cmd failed");	exits("");	return 0;}

⌨️ 快捷键说明

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