Echo Lineinitial commit9fd65008 years agoHistory
901 lines · 18.7 KB · C
RawDownload
/* * cpu.c - Make a connection to a cpu server */ #include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <authsrv.h>#include <libsec.h>#include "args.h"#include "drawterm.h" #define MaxStr 128 static void	usage(void);static void	writestr(int, char*, char*, int);static int	readstr(int, char*, int);static char 	*keyspec = "";static AuthInfo *p9any(int);static int	getkey(Authkey*, char*, char*, char*, char*);static int	findkey(Authkey*, char*, char*, char*); static char	*host = "echoline.org";static int	aanfilter;static int	aanto = 3600 * 24;static int	norcpu;static int	nokbd;static int	nogfx; static char	*ealgs = "rc4_256 sha1"; /* authentication mechanisms */static int	p9authssl(int);static int	p9authtls(int); char *authserver = "echoline.org";char *secstore;char *user, *pass;char secstorebuf[65536]; extern void	guimain(void); char*estrdup(char *s){	s = strdup(s);	if(s == nil)		sysfatal("out of memory");	return s;} static voidending(void){	panic("ending");} intmountfactotum(void){	int fd;		if((fd = dialfactotum()) < 0)		return -1;	if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){		fprint(2, "mount factotum: %r\n");		return -1;	}	if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){		fprint(2, "open /mnt/factotum/ctl: %r\n");		return -1;	}	close(fd);	return 0;} static intstartaan(char *host, int fd){	static char script[] ="~ $#netdir 1 || netdir=/net/tcp/clone\n""netdir=`{basename -d $netdir} || exit\n""<>$netdir/clone {\n""	netdir=$netdir/`{read} || exit\n""	>[3] $netdir/ctl {\n""		echo -n 'announce *!0' >[1=3]\n""		echo `{cat $netdir/local} || exit\n""		bind '#|' /mnt/aan || exit\n""		exec aan -m $aanto $netdir <>/mnt/aan/data1 >[1=0] >[2]/dev/null &\n""	}\n""}\n""<>/mnt/aan/data >[1=0] >[2]/dev/null {\n""	rfork n\n""	fn server {\n""		echo -n aanserver $netdir >/proc/$pid/args\n""		rm -f /env/^('fn#server' aanto)\n""		. <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]\n""	}\n""	exec tlssrv -A /bin/rc -c server\n""	exit\n""}\n";	char buf[128], *p, *na;	int n; 	snprint(buf, sizeof buf, "aanto=%d\n", aanto);	if(fprint(fd, "%7ld\n%s%s", strlen(buf)+strlen(script), buf, script) < 0)		sysfatal("sending aan script: %r");	n = read(fd, buf, sizeof(buf)-1);	close(fd); 	while(n > 0 && buf[n-1] == '\n') n--;	if(n <= 0) return -1;	buf[n] = 0;	if((p = strrchr(buf, '!')) != nil)		na = strdup(netmkaddr(host, "tcp", p+1));	else		na = strdup(buf); 	return aanclient(na, aanto);} voidrcpu(char *host, char *cmd){	static char script[] = "syscall fversion 0 65536 buf 256 >/dev/null >[2=1]\n""mount -nc /fd/0 /mnt/term || exit\n""bind -q /mnt/term/dev/cons /dev/cons\n""if(test -r /mnt/term/dev/kbd){\n""	</dev/cons >/dev/cons >[2=1] aux/kbdfs -dq -m /mnt/term/dev\n""	bind -q /mnt/term/dev/cons /dev/cons\n""}\n""</dev/cons >/dev/cons >[2=1] service=cpu %s\n""echo -n hangup >/proc/$pid/notepg\n";	int fd; 	if((fd = dial(netmkaddr(host, "tcp", "rcpu"), nil, nil, nil)) < 0)		return; 	/* provide /dev/kbd for kbdfs */	if(!nokbd)		bind("#b", "/dev", MAFTER); 	fd = p9authtls(fd);	if(aanfilter){		fd = startaan(host, fd);		if(fd < 0)			sysfatal("startaan: %r");		fd = p9authtls(fd);	}	memset(secstorebuf, 0, sizeof(secstorebuf));	/* forget secstore secrets */ 	if(cmd == nil)		cmd = smprint(script, "rc -li");	else {		char *run = smprint("rc -lc %q", cmd);		cmd = smprint(script, run);		free(run);	}	if(fprint(fd, "%7ld\n%s", strlen(cmd), cmd) < 0)		sysfatal("sending script: %r");	free(cmd); 	/* Begin serving the namespace */	exportfs(fd);} voidncpu(char *host, char *cmd){	char buf[MaxStr];	int fd; 	if((fd = dial(netmkaddr(host, "tcp", "ncpu"), nil, nil, nil)) < 0)		return; 	/* negotiate authentication mechanism */	strcpy(buf, "p9");	if(ealgs != nil){		strcat(buf, " ");		strcat(buf, ealgs);	}	writestr(fd, buf, "negotiating authentication method", 0);	if(readstr(fd, buf, sizeof buf) < 0)		sysfatal("can't negotiate authentication method: %r");	if(*buf)		sysfatal("%s", buf); 	/* authenticate and encrypt the channel */	fd = p9authssl(fd); 	/* tell remote side the command */	if(cmd != nil){		cmd = smprint("!%s", cmd);		writestr(fd, cmd, "cmd", 0);		free(cmd);	} 	/* Tell the remote side where our working directory is */	if(getcwd(buf, sizeof(buf)) == 0)		writestr(fd, "NO", "dir", 0);	else		writestr(fd, buf, "dir", 0); 	/* 	 *  Wait for the other end to execute and start our file service	 *  of /mnt/term	 */	if(readstr(fd, buf, sizeof(buf)) < 0)		sysfatal("waiting for FS: %r");	if(strncmp("FS", buf, 2) != 0) {		print("remote cpu: %s", buf);		exits(buf);	} 	if(readstr(fd, buf, sizeof(buf)) < 0)		sysfatal("waiting for remote export: %r");	if(strcmp(buf, "/") != 0){		print("remote cpu: %s", buf);		exits(buf);	}	write(fd, "OK", 2); 	/* Begin serving the gnot namespace */	exportfs(fd);} voidusage(void){	fprint(2, "usage: %s [-GBO] "		"[-h host] [-u user] [-a authserver] [-s secstore] "		"[-e 'crypt hash'] [-k keypattern] "		"[-p] [-t timeout] "		"[-r root] [-c cmd ...]\n", argv0);	exits("usage");} static char *cmd; extern void cpubody(void); voidcpumain(int argc, char **argv){	char *s; 	user = getenv("USER");	pass = getenv("PASS");	host = getenv("cpu");	authserver = getenv("auth"); 	ARGBEGIN{	case 'G':		nogfx = 1;		/* wet floor */	case 'B':		nokbd = 1;		break;	case 'O':		norcpu = 1;		break;	case 'p':		aanfilter = 1;		break;	case 't':		aanto = (int)strtol(EARGF(usage()), nil, 0);		break;	case 'h':		host = EARGF(usage());		break;	case 'a':		authserver = EARGF(usage());		break;	case 's':		secstore = EARGF(usage());		break;	case 'e':		ealgs = EARGF(usage());		if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)			ealgs = nil;		break;	case 'k':		keyspec = EARGF(usage());		break;	case 'u':		user = EARGF(usage());		break;	case 'r':		s = smprint("/root/%s", EARGF(usage()));		cleanname(s);		if(bind(s, "/root", MREPL) < 0)			panic("bind /root: %r");		free(s);		break;	case 'c':		cmd = estrdup(EARGF(usage()));		while((s = ARGF()) != nil){			char *old = cmd;			cmd = smprint("%s %q", cmd, s);			free(old);		}		break;	default:		usage();	}ARGEND; 	if(argc != 0)		usage(); 	if(!nogfx)		guimain();	else		cpubody();} voidcpubody(void){	char *s; 	if(!nogfx){		if(bind("#i", "/dev", MBEFORE) < 0)			panic("bind #i: %r");		if(bind("#m", "/dev", MBEFORE) < 0)			panic("bind #m: %r");		if(cmd == nil)			atexit(ending);	}	if(bind("/root", "/", MAFTER) < 0)		panic("bind /root: %r"); 	if(host == nil)		if((host = readcons("cpu", "cpu", 0)) == nil)			sysfatal("user terminated input"); 	if(authserver == nil)		if((authserver = readcons("auth", host, 0)) == nil)			sysfatal("user terminated input"); 	if(user == nil)		if((user = readcons("user", "glenda", 0)) == nil)			sysfatal("user terminated input"); 	if(mountfactotum() < 0){		if(secstore == nil)			secstore = authserver;	 	if(havesecstore(secstore, user)){			s = secstorefetch(secstore, user, pass);			if(s){				if(strlen(s) >= sizeof secstorebuf)					sysfatal("secstore data too big");				strcpy(secstorebuf, s);			}		}	} 	if(!norcpu)		rcpu(host, cmd); 	ncpu(host, cmd); 	sysfatal("can't dial %s: %r", host);} voidwritestr(int fd, char *str, char *thing, int ignore){	int l, n; 	l = strlen(str);	n = write(fd, str, l+1);	if(!ignore && n < 0)		sysfatal("writing network: %s: %r", thing);} intreadstr(int fd, char *str, int len){	int n; 	while(len) {		n = read(fd, str, 1);		if(n < 0) 			return -1;		if(*str == '\0')			return 0;		str++;		len--;	}	return -1;} static voidmksecret(char *t, uchar *f){	sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",		f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);} /* *  plan9 authentication followed by rc4 encryption */static intp9authssl(int fd){	uchar key[16];	uchar digest[SHA1dlen];	char fromclientsecret[21];	char fromserversecret[21];	AuthInfo *ai; 	ai = p9any(fd);	memset(secstorebuf, 0, sizeof(secstorebuf));	/* forget secstore secrets */	if(ai == nil)		sysfatal("can't authenticate: %r"); 	if(ealgs == nil)		return fd; 	if(ai->nsecret < 8){		sysfatal("p9authssl: secret too small");		return -1;	}	memmove(key+4, ai->secret, 8); 	/* exchange random numbers */	genrandom(key, 4);	if(write(fd, key, 4) != 4){		sysfatal("p9authssl: write random: %r");		return -1;	}	if(readn(fd, key+12, 4) != 4){		sysfatal("p9authssl: read random: %r");		return -1;	} 	/* scramble into two secrets */	sha1(key, sizeof(key), digest, nil);	mksecret(fromclientsecret, digest);	mksecret(fromserversecret, digest+10); 	/* set up encryption */	fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);	if(fd < 0)		sysfatal("p9authssl: pushssl: %r"); 	return fd;} /* * p9any authentication followed by tls-psk encryption */static intp9authtls(int fd){	AuthInfo *ai;	TLSconn *conn; 	ai = p9any(fd);	if(ai == nil)		sysfatal("can't authenticate: %r"); 	conn = mallocz(sizeof(TLSconn), 1);	conn->pskID = "p9secret";	conn->psk = ai->secret;	conn->psklen = ai->nsecret; 	fd = tlsClient(fd, conn);	if(fd < 0)		sysfatal("tlsClient: %r"); 	auth_freeAI(ai);	free(conn->sessionID);	free(conn); 	return fd;} intauthdial(char *net, char *dom){	return dial(netmkaddr(authserver, "tcp", "ticket"), 0, 0, 0);} static intgetastickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen){	int asfd, rv;	char *dom; 	dom = tr->authdom;	asfd = authdial(nil, dom);	if(asfd < 0)		return -1;	if(y != nil){		PAKpriv p; 		rv = -1;

Lines 1–500 of 901.