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")); }}
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"));
}
}