echolineinitial commit1a6a37b8 years agoHistory
272 lines · 5.4 KB · JavaScript
RawDownload
var cpubuf;var oncpumsg;var authdom;var conn;var state; var TicketReq = ["i1:type","s28:authid","s48:authdom","b8:chal","s28:hostid","s28:uid"];var Ticket = ["i1:num","b8:chal","s28:cuid","s28:suid","B7:key"];var Authenticator = ["i1:num","b8:chal","i4:id"]; function fatal(msg) {	throw msg;} function randomdata(n) {	var s, i; 	s = "";	for(i = 0; i < n; i++)		s += String.fromCharCode(Math.floor(Math.random() * 256));	return s;} function newWebSocket(url) {	if(window.WebSocket != undefined)		return new WebSocket(url);	if(window.MozWebSocket != undefined)		return new MozWebSocket(url);	fatal("no websockets");} function unpack(data, fmt) {	var x,s,t,n,i,l,r,p,v; 	i = 0;	r = {};	for(x in fmt){		s = fmt[x].split(':', 2);		t = s[0];		n = s[1];		l = parseInt(t.substring(1))		t = t.substring(0, 1);		if(t == "R"){			r[n] = data.substring(i);			break;		}		s = data.substring(i, i+l);		i += l;		switch(t){		case "i":			v = 0;			for(p = s.length - 1; p >= 0; p--){				v *= 256;				v += s.charCodeAt(p);			}			r[n] = v;			break;		case "j":			v = 0;			for(p = s.length - 1; p >= 0; p--){				v *= 256;				v += s.charCodeAt(p);			}			p = 1 << (s.length * 8 - 1);			if((v & p) != 0){				v &= ~p;				v = - 1 - v;			}			r[n] = v;			break;		case "s":			v = s.indexOf(String.fromCharCode(0));			if(v < 0)				r[n] = s;			else				r[n] = s.substring(0, v);			break;		case "S":			v = 0;			for(p = s.length - 1; p >= 0; p--){				v *= 256;				v += s.charCodeAt(p);			}			r[n] = data.substr(i, v);			i += v;			break;		case "b":			r[n] = s;			break;		case "B":			r[n] = Array(l);			for(p = 0; p < l; p++)				r[n][p] = s.charCodeAt(p);			break;		default:			throw "unknown type " + t + " used with unpack";		}	}	return r;} function pack(data, fmt) {	var r,s,t,n,l,v; 	r = "";	for(x in fmt){		s = fmt[x].split(':', 2);		t = s[0];		n = s[1];		l = parseInt(t.substring(1))		t = t.substring(0, 1);		s = data[n];		if(s == undefined)			throw "undefined field " + n + " in pack";		switch(t){		case "i":			for(p = 0; p < l; p++){				r += String.fromCharCode(s & 0xFF);				s >>>= 8;			}			break;		case "s":		case "b":			if(s.length > l)				r += s.substring(0, l);			else{				r += s;				if(s.length < l)					r += Array(l - s.length + 1).join("\0");			}			break;		case "S":			v = s.length;			for(p = 0; p < l; p++){				r += String.fromCharCode(v & 0xFF);				v >>>= 8;			}			r += s;			break;		case "R":			r += s;			break;		default:			throw "unknown type " + t + " used with pack";		}	}	return r;} var password; function startauth() {	username = prompt("username", "");	password = prompt("password", ""); 	cpubuf = "";	conn = newWebSocket("ws://plan9.echoline.org:8080/ncpu");	conn.onmessage = function(evt) {		cpubuf += window.atob(evt.data);		if(oncpumsg)			while(cpubuf != "" && oncpumsg() > 0)				;	}	conn.onerror = fatal;	conn.onopen = function(evt) {		var cticket, cchal; 		state = 0;		oncpumsg = function() {			var i, s, arr, arr2; 			switch(state){			case 0: case 1: case 4: case 5:				i = cpubuf.indexOf(String.fromCharCode(0));				if(i < 0)					return -1;				s = cpubuf.substring(0, i);				cpubuf = cpubuf.substring(i+1);				break;			case 2:				i = 141;				if(cpubuf.length < i)					return -1;				s = cpubuf.substring(0, i);				cpubuf = cpubuf.substring(i);				break;			case 3:				i = 13;				if(cpubuf.length < i)					return -1;				s = cpubuf.substring(0, i);				cpubuf = cpubuf.substring(i);				break;			}			switch(state){			case 0:				state++;				if(s != "")					fatal(s);				break;			case 1:				state++;				arr = s.split(' ');				for(i = 0; i < arr.length; i++){					arr2 = arr[i].split('@');					if(arr2[0] == 'p9sk1'){						conn.send(window.btoa(arr2[0] + ' ' + arr2[1] + '\0'));						cchal = randomdata(8);						conn.send(window.btoa(cchal));						authdom=arr2[1];						break;					}				}				if(!authdom)					fatal("p9sk1 not available");				document.getElementById('terminal').firstChild.writeterminal('dom: ' + authdom + '\n');				break;			case 2:				var chal; 				state++;				s = unpack(s, TicketReq);				s.type = 1;				s.hostid = username;				s.uid = username;				chal = s.chal;				s = pack(s, TicketReq);				authconn = newWebSocket("ws://plan9.echoline.org:8080/auth");				authconn.onmessage = function(evt) {					var buf, sticket; 					authconn.close()					buf = atob(evt.data);					if(buf.length < 145)						fatal("AS ticket too short");					if(buf.charCodeAt(0) != 4)						fatal("AS protocol botch " + buf.charCodeAt(0));					cticket = unpack(decrypt(passtokey(password), buf.substr(1, 72)), Ticket);					if(cticket.num != 65)						fatal("wrong password");					sticket = buf.substr(73, 72);					conn.send(btoa(sticket + encrypt(cticket.key, pack({num:67, chal:chal, id:0}, Authenticator))));				}				authconn.onopen = function() {					authconn.send(btoa(s));				}				break;			case 3:				state++;				s = unpack(decrypt(cticket.key, s), Authenticator);				if(s.num != 66 || s.chal != cchal || s.id != 0)					fatal("cpu auth protocol botch");				conn.send(btoa("! /bin/rc\0"));				conn.send(btoa("NO\0"));				break;			case 4:				state++;				if(s != "FS")					fatal("want FS got " + s);				break;			case 5:				state++;				oncpumsg = got9praw;				if(s != "/")					fatal("want / got " + s);				conn.send(btoa("OK"));			}			return 1;		}		conn.send(window.btoa("p9\0"));	}}