1033 lines
31 KiB
JavaScript
1033 lines
31 KiB
JavaScript
/**
|
|
** ==============================
|
|
** O O O OOOO
|
|
** O O O O O O
|
|
** O O O O O O
|
|
** OOOO OOOO O OOO OOOO
|
|
** O O O O O O O
|
|
** O O O O O O O
|
|
** OOOO OOOO O O OOOO
|
|
** ==============================
|
|
** Dr. Stefan Bosse http://www.bsslab.de
|
|
**
|
|
** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
|
|
** BY THE AUTHOR.
|
|
** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
|
|
** MODIFIED, OR OTHERWISE USED IN A CONTEXT
|
|
** OUTSIDE OF THE SOFTWARE SYSTEM.
|
|
**
|
|
** $AUTHORS: Stefan Bosse
|
|
** $INITIAL: (C) 2006-2018 bLAB
|
|
** $CREATED: 3-5-15 by sbosse.
|
|
** $VERSION: 1.2.6
|
|
**
|
|
** $INFO:
|
|
**
|
|
** DOS: Networking, Commands, Status/Error codes, ..
|
|
**
|
|
** $ENDOFINFO
|
|
*/
|
|
"use strict";
|
|
var log = 0;
|
|
|
|
var util = Require('util');
|
|
|
|
var Io = Require('com/io');
|
|
var Comp = Require('com/compat');
|
|
var String = Comp.string;
|
|
var Array = Comp.array;
|
|
var Perv =Comp.pervasives;
|
|
var Des48 = Require('dos/des48');
|
|
var Base64 = Require('os/base64');
|
|
var Rand = Comp.random;
|
|
var Fs = Require('fs');
|
|
|
|
//var xmldoc = Require('xmldoc');
|
|
|
|
|
|
function pad(str,size) {
|
|
while (str.length < (size || 2)) {str = "0" + str;}
|
|
return str;
|
|
}
|
|
|
|
|
|
/** Direction
|
|
*
|
|
var Direction = {
|
|
NORTH:1,
|
|
WEST:2,
|
|
EAST:3,
|
|
SOUTH:4,
|
|
ORIGIN:5,
|
|
tostring:function (i) {
|
|
switch (i) {
|
|
case 1: return 'NORTH';
|
|
case 2: return 'WEST';
|
|
case 3: return 'EAST';
|
|
case 4: return 'SOUTH';
|
|
case 5: return 'ORIGIN';
|
|
default: return 'Direction?';
|
|
}
|
|
}
|
|
};
|
|
*/
|
|
|
|
|
|
// Standard Object Service
|
|
var STD_FIRST_COM = 1000;
|
|
var STD_LAST_COM = 1999;
|
|
var STD_FIRST_ERR = (-STD_FIRST_COM);
|
|
var STD_LAST_ERR = (-STD_LAST_COM);
|
|
|
|
// File Server
|
|
var AFS_FIRST_COM = 2000;
|
|
var AFS_LAST_COM = 2099;
|
|
var AFS_FIRST_ERR = (-AFS_FIRST_COM);
|
|
var AFS_LAST_ERR = (-AFS_LAST_COM);
|
|
var AFS_REQBUFSZ = 1024*32;
|
|
|
|
|
|
// Directory and Name Server
|
|
var DNS_FIRST_COM = 2100;
|
|
var DNS_LAST_COM = 2199;
|
|
var DNS_FIRST_ERR = (-DNS_FIRST_COM);
|
|
var DNS_LAST_ERR = (-DNS_LAST_COM);
|
|
var DNS_MAXCOLUMNS = 4;
|
|
|
|
// System Process Server (incl. Agent Platform Manager)
|
|
var PS_FIRST_COM = 2200;
|
|
var PS_LAST_COM = 2299;
|
|
var PS_FIRST_ERR = (-PS_FIRST_COM);
|
|
var PS_LAST_ERR = (-PS_LAST_COM);
|
|
|
|
// Broker Server
|
|
var BR_FIRST_COM = 2300;
|
|
var BR_LAST_COM = 2399;
|
|
var BR_FIRST_ERR = (-BR_FIRST_COM);
|
|
var BR_LAST_ERR = (-BR_LAST_COM);
|
|
/** RPC Status
|
|
*
|
|
* @enum {number}
|
|
*/
|
|
var Status = {
|
|
STD_OK:0,
|
|
STD_CAPBAD : STD_FIRST_ERR,
|
|
STD_COMBAD : (STD_FIRST_ERR-1),
|
|
STD_ARGBAD : (STD_FIRST_ERR-2),
|
|
STD_NOTNOW : (STD_FIRST_ERR-3),
|
|
STD_NOSPACE : (STD_FIRST_ERR-4),
|
|
STD_DENIED : (STD_FIRST_ERR-5),
|
|
STD_NOMEM : (STD_FIRST_ERR-6),
|
|
STD_EXISTS : (STD_FIRST_ERR-7),
|
|
STD_NOTFOUND : (STD_FIRST_ERR-8),
|
|
STD_SYSERR : (STD_FIRST_ERR-9),
|
|
STD_INTR : (STD_FIRST_ERR-10),
|
|
STD_OVERFLOW : (STD_FIRST_ERR-11),
|
|
STD_WRITEPROT : (STD_FIRST_ERR-12),
|
|
STD_NOMEDIUM : (STD_FIRST_ERR-13),
|
|
STD_IOERR : (STD_FIRST_ERR-14),
|
|
STD_WRONGSRV : (STD_FIRST_ERR-15),
|
|
STD_OBJBAD : (STD_FIRST_ERR-16),
|
|
STD_UNKNOWN : (STD_FIRST_ERR-17),
|
|
DNS_UNAVAIL : (DNS_FIRST_ERR -1),
|
|
DNS_NOTEMPTY : (DNS_FIRST_ERR -2),
|
|
DNS_UNREACH : (DNS_FIRST_ERR -3),
|
|
DNS_CLASH : (DNS_FIRST_ERR -4),
|
|
RPC_FAILURE : -1,
|
|
BUF_OVERFLOW : -2,
|
|
print: function(stat) {
|
|
switch(stat) {
|
|
case Status.STD_OK : return 'STD_OK';
|
|
case Status.STD_CAPBAD : return 'STD_CAPBAD';
|
|
case Status.STD_COMBAD : return 'STD_COMBAD';
|
|
case Status.STD_ARGBAD : return 'STD_ARGBAD';
|
|
case Status.STD_NOTNOW : return 'STD_NOTNOW';
|
|
case Status.STD_NOSPACE : return 'STD_NOSPACE';
|
|
case Status.STD_DENIED : return 'STD_DENIED';
|
|
case Status.STD_NOMEM : return 'STD_NOMEM';
|
|
case Status.STD_EXISTS : return 'STD_EXISTS';
|
|
case Status.STD_NOTFOUND : return 'STD_NOTFOUND';
|
|
case Status.STD_SYSERR : return 'STD_SYSERR';
|
|
case Status.STD_INTR : return 'STD_INTR';
|
|
case Status.STD_OVERFLOW : return 'STD_OVERFLOW';
|
|
case Status.STD_WRITEPROT : return 'STD_WRITEPROT';
|
|
case Status.STD_NOMEDIUM : return 'STD_NOMEDIUM';
|
|
case Status.STD_IOERR : return 'STD_IOERR';
|
|
case Status.STD_WRONGSRV : return 'STD_WRONGSRV';
|
|
case Status.STD_OBJBAD : return 'STD_OBJBAD';
|
|
case Status.STD_UNKNOWN : return 'STD_UNKNOWN';
|
|
case Status.DNS_UNAVAIL : return 'DNS_UNAVAIL';
|
|
case Status.DNS_NOTEMPTY : return 'DNS_NOTEMPTY';
|
|
case Status.DNS_UNREACH : return 'DNS_UNREACH';
|
|
case Status.DNS_CLASH : return 'DNS_CLASH';
|
|
case Status.RPC_FAILURE : return 'RPC_FAILURE';
|
|
case Status.BUF_OVERFLOW : return 'BUF_OVERFLOW';
|
|
default : return '"'+stat+'"';
|
|
}
|
|
}
|
|
};
|
|
|
|
/** RPC Command
|
|
*
|
|
* @enum {number}
|
|
*/
|
|
|
|
var Command = {
|
|
/*
|
|
** Standard Commands
|
|
*/
|
|
STD_MONITOR : STD_FIRST_COM,
|
|
STD_AGE : (STD_FIRST_COM+1),
|
|
STD_COPY : (STD_FIRST_COM + 2),
|
|
STD_DESTROY : (STD_FIRST_COM + 3),
|
|
STD_INFO : (STD_FIRST_COM + 4),
|
|
STD_RESTRICT : (STD_FIRST_COM + 5),
|
|
STD_STATUS : (STD_FIRST_COM + 6),
|
|
STD_TOUCH : (STD_FIRST_COM + 7),
|
|
STD_GETPARAMS : (STD_FIRST_COM + 8),
|
|
STD_SETPARAMS : (STD_FIRST_COM + 9),
|
|
STD_NTOUCH : (STD_FIRST_COM + 10),
|
|
STD_EXIT : (STD_FIRST_COM + 11),
|
|
STD_RIGHTS : (STD_FIRST_COM + 12),
|
|
STD_EXEC : (STD_FIRST_COM + 13),
|
|
STD_LOCATION : (STD_FIRST_COM + 20),
|
|
STD_LABEL : (STD_FIRST_COM + 21),
|
|
|
|
/*
|
|
** AFC Commands
|
|
*/
|
|
AFS_CREATE : (AFS_FIRST_COM + 1),
|
|
AFS_DELETE : (AFS_FIRST_COM + 2),
|
|
AFS_FSCK : (AFS_FIRST_COM + 3),
|
|
AFS_INSERT : (AFS_FIRST_COM + 4),
|
|
AFS_MODIFY : (AFS_FIRST_COM + 5),
|
|
AFS_READ : (AFS_FIRST_COM + 6),
|
|
AFS_SIZE : (AFS_FIRST_COM + 7),
|
|
AFS_DISK_COMPACT : (AFS_FIRST_COM + 8),
|
|
AFS_SYNC : (AFS_FIRST_COM + 9),
|
|
AFS_DESTROY : (AFS_FIRST_COM + 10),
|
|
|
|
/*
|
|
** DNS Commands
|
|
*/
|
|
|
|
DNS_CREATE : (DNS_FIRST_COM),
|
|
DNS_DISCARD : (DNS_FIRST_COM + 1),
|
|
DNS_LIST : (DNS_FIRST_COM + 2),
|
|
DNS_APPEND : (DNS_FIRST_COM + 3),
|
|
DNS_CHMOD : (DNS_FIRST_COM + 4),
|
|
DNS_DELETE : (DNS_FIRST_COM + 5),
|
|
DNS_LOOKUP : (DNS_FIRST_COM + 6),
|
|
DNS_SETLOOKUP : (DNS_FIRST_COM + 7),
|
|
DNS_INSTALL : (DNS_FIRST_COM + 8),
|
|
DNS_REPLACE : (DNS_FIRST_COM + 10),
|
|
DNS_GETMASKS : (DNS_FIRST_COM + 11),
|
|
DNS_GETSEQNR : (DNS_FIRST_COM + 12),
|
|
DNS_RENAME : (DNS_FIRST_COM + 13),
|
|
DNS_GETROOT : (DNS_FIRST_COM + 14),
|
|
DNS_GETDEFAFS : (DNS_FIRST_COM + 15),
|
|
|
|
PS_STUN : (PS_FIRST_COM), // Kill a process/ create a snapshot
|
|
PS_MIGRATE : (PS_FIRST_COM+1), // Execute a process from a snapshot after migration (->next+)
|
|
PS_EXEC : (PS_FIRST_COM+2), // Execute a process from a snapshot (->next)
|
|
PS_WRITE : (PS_FIRST_COM+4), // Store a process class template
|
|
PS_READ : (PS_FIRST_COM+5), // Get a process class template
|
|
PS_CREATE : (PS_FIRST_COM+6), // Create a process from a template and execute
|
|
PS_FORK : (PS_FIRST_COM+7), // Fork a process from a running process
|
|
PS_SIGNAL : (PS_FIRST_COM+8), // Send a signal to a process
|
|
|
|
BR_CONNECT : (BR_FIRST_COM),
|
|
BR_DISCONN : (BR_FIRST_COM+1),
|
|
|
|
print: function(cmd) {
|
|
switch(cmd) {
|
|
case Command.STD_MONITOR : return 'STD_MONITOR';
|
|
case Command.STD_AGE : return 'STD_AGE';
|
|
case Command.STD_COPY : return 'STD_COPY';
|
|
case Command.STD_DESTROY : return 'STD_DESTROY';
|
|
case Command.STD_INFO : return 'STD_INFO';
|
|
case Command.STD_RESTRICT : return 'STD_RESTRICT';
|
|
case Command.STD_STATUS : return 'STD_STATUS';
|
|
case Command.STD_TOUCH : return 'STD_TOUCH';
|
|
case Command.STD_GETPARAMS : return 'STD_GETPARAMS';
|
|
case Command.STD_SETPARAMS : return 'STD_SETPARAMS';
|
|
case Command.STD_NTOUCH : return 'STD_NTOUCH';
|
|
case Command.STD_EXIT : return 'STD_EXIT';
|
|
case Command.STD_RIGHTS : return 'STD_RIGHTS';
|
|
case Command.STD_EXEC : return 'STD_EXEC';
|
|
case Command.STD_LOCATION : return 'STD_LOCATION';
|
|
case Command.STD_LABEL : return 'STD_LABEL';
|
|
case Command.AFS_CREATE : return 'AFS_CREATE';
|
|
case Command.AFS_DELETE : return 'AFS_DELETE';
|
|
case Command.AFS_FSCK : return 'AFS_FSCK';
|
|
case Command.AFS_INSERT : return 'AFS_INSERT';
|
|
case Command.AFS_MODIFY : return 'AFS_MODIFY';
|
|
case Command.AFS_READ : return 'AFS_READ';
|
|
case Command.AFS_SIZE : return 'AFS_SIZE';
|
|
case Command.AFS_DISK_COMPACT : return 'AFS_DISK_COMPACT';
|
|
case Command.AFS_SYNC : return 'AFS_SYNC';
|
|
case Command.AFS_DESTROY : return 'AFS_DESTROY';
|
|
case Command.DNS_CREATE : return 'DNS_CREATE';
|
|
case Command.DNS_DISCARD : return 'DNS_DISCARD';
|
|
case Command.DNS_LIST : return 'DNS_LIST';
|
|
case Command.DNS_APPEND : return 'DNS_APPEND';
|
|
case Command.DNS_CHMOD : return 'DNS_CHMOD';
|
|
case Command.DNS_DELETE : return 'DNS_DELETE';
|
|
case Command.DNS_LOOKUP : return 'DNS_LOOKUP';
|
|
case Command.DNS_SETLOOKUP : return 'DNS_SETLOOKUP';
|
|
case Command.DNS_INSTALL : return 'DNS_INSTALL';
|
|
case Command.DNS_REPLACE : return 'DNS_REPLACE';
|
|
case Command.DNS_GETMASKS : return 'DNS_GETMASKS';
|
|
case Command.DNS_GETSEQNR : return 'DNS_GETSEQNR';
|
|
case Command.DNS_RENAME : return 'DNS_RENAME';
|
|
case Command.DNS_GETROOT : return 'DNS_GETRROT';
|
|
case Command.DNS_GETDEFAFS : return 'DNS_GETDEFAFS';
|
|
case Command.PS_STUN : return 'PS_STUN';
|
|
case Command.PS_EXEC : return 'PS_EXEC';
|
|
case Command.PS_MIGRATE : return 'PS_MIGRATE';
|
|
case Command.PS_READ : return 'PS_READ';
|
|
case Command.PS_WRITE : return 'PS_WRITE';
|
|
case Command.PS_CREATE : return 'PS_CREATE';
|
|
case Command.PS_FORK : return 'PS_FORK';
|
|
case Command.PS_SIGNAL : return 'PS_SIGNAL';
|
|
case Command.BR_CONNECT : return 'BR_CONNECT';
|
|
case Command.BR_DISCONN : return 'BR_DISCONN';
|
|
default: return '"'+cmd+'"';
|
|
}
|
|
|
|
|
|
}
|
|
};
|
|
|
|
var PORT_SIZE = 6;
|
|
var PRIV_SIZE = 4+PORT_SIZE;
|
|
var CAP_SIZE = 16;
|
|
|
|
/** Object Rights
|
|
*
|
|
* @enum {number}
|
|
*/
|
|
var Rights = {
|
|
AFS_RGT_READ : 0x1,
|
|
AFS_RGT_CREATE : 0x2,
|
|
AFS_RGT_MODIFY : 0x4,
|
|
AFS_RGT_DESTROY : 0x8,
|
|
AFS_RGT_ADMIN : 0x80,
|
|
|
|
DNS_COLMASK : ((1 << DNS_MAXCOLUMNS) - 1), // Rights to access specific columns of a directory row, one bit, one column.
|
|
DNS_RGT_COLALL : ((1 << DNS_MAXCOLUMNS) - 1),
|
|
DNS_RGT_COL1 : 0x01,
|
|
DNS_RGT_OWNER : 0x01,
|
|
DNS_RGT_COL2 : 0x02,
|
|
DNS_RGT_GROUP : 0x02,
|
|
DNS_RGT_COL3 : 0x04,
|
|
DNS_RGT_OTHERS : 0x04,
|
|
DNS_RGT_COL4 : 0x08,
|
|
DNS_RGT_READ : 0x10,
|
|
DNS_RGT_CREATE : 0x20,
|
|
DNS_RGT_MODIFY : 0x40,
|
|
DNS_RGT_DELETE : 0x80,
|
|
|
|
HOST_INFO : 0x01,
|
|
HOST_READ : 0x02,
|
|
HOST_WRITE : 0x04,
|
|
HOST_EXEC : 0x08,
|
|
|
|
PSR_READ : 0x01,
|
|
PSR_WRITE : 0x02,
|
|
PSR_CREATE : 0x04,
|
|
PSR_DELETE : 0x08,
|
|
PSR_EXEC : 0x10,
|
|
PSR_KILL : 0x20,
|
|
PSR_ALL : 0xff,
|
|
|
|
NEG_SCHED : 0x08,
|
|
NEG_CPU : 0x10,
|
|
NEG_RES : 0x20,
|
|
NEG_LEVEL : 0x40,
|
|
|
|
PRV_ALL_RIGHTS : 0xff
|
|
|
|
};
|
|
|
|
|
|
|
|
var DEF_RPC_MAX_HOP = 4;
|
|
|
|
var priv2pub_cache = [];
|
|
|
|
/**
|
|
*
|
|
* @param {number []} [port_vals]
|
|
* @returns {string}
|
|
*/
|
|
var port = function (port_vals) {
|
|
if (port_vals==undefined) port_vals=[0,0,0,0,0,0];
|
|
var port='';
|
|
for(var i = 0; i< PORT_SIZE;i++) {
|
|
port=port+Perv.char_of_int(port_vals[i]);
|
|
}
|
|
return port;
|
|
|
|
};
|
|
/**
|
|
*
|
|
* @param {number} [obj]
|
|
* @param {number} [rights]
|
|
* @param {port} [rand]
|
|
* @constructor
|
|
*/
|
|
var privat = function (obj,rights,rand) {
|
|
if (obj==undefined) {
|
|
// Create empty private field
|
|
this.prv_obj=0;
|
|
this.prv_rights=0;
|
|
this.prv_rand=port();
|
|
} else {
|
|
this.prv_obj = obj; // Integer
|
|
this.prv_rights = rights; // Integer
|
|
this.prv_rand = rand; // Port=string
|
|
}
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param {port} [cap_port]
|
|
* @param {privat} [cap_priv]
|
|
* @constructor
|
|
*/
|
|
var capability = function(cap_port, cap_priv) {
|
|
if (cap_port==undefined) {
|
|
// Create empty capability
|
|
this.cap_port = port();
|
|
this.cap_priv = new privat();
|
|
} else {
|
|
this.cap_port = cap_port; // Port=string
|
|
if (cap_priv==undefined)
|
|
this.cap_priv = new privat();
|
|
else
|
|
this.cap_priv = cap_priv; // Private
|
|
}
|
|
};
|
|
|
|
/*
|
|
** RPC communication is XML based using the HTTP interface.
|
|
** RPC communication is synchronous, hence a callback
|
|
** function is used to handle the reply (acknowledge).
|
|
*/
|
|
/**
|
|
*
|
|
* @param {port} [h_port]
|
|
* @param {privat} [h_priv]
|
|
* @param {Command} [h_command]
|
|
* @param {(Status.STD_OK|*)} [h_status]
|
|
* @constructor
|
|
*/
|
|
var header = function(h_port,h_priv,h_command,h_status) {
|
|
if (h_port==undefined) {
|
|
// Create empty header
|
|
this.h_port = port();
|
|
this.h_priv = new privat();
|
|
this.h_command = undefined;
|
|
this.h_status = undefined;
|
|
} else {
|
|
this.h_port = h_port;
|
|
this.h_priv = h_priv;
|
|
this.h_command = h_command;
|
|
this.h_status = h_status;
|
|
}
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param {number} [obj]
|
|
* @param {number} [rights]
|
|
* @param {port} [rand]
|
|
* @returns {privat}
|
|
*/
|
|
function Private(obj,rights,rand) {
|
|
var _obj = new privat(obj,rights,rand);
|
|
Object.preventExtensions(_obj);
|
|
return _obj;
|
|
}
|
|
/**
|
|
*
|
|
* @param {port} [cap_port]
|
|
* @param {privat} [cap_priv]
|
|
* @returns {capability}
|
|
*/
|
|
function Capability (cap_port, cap_priv) {
|
|
var obj = new capability(cap_port, cap_priv);
|
|
Object.preventExtensions(obj);
|
|
return obj;
|
|
}
|
|
/**
|
|
*
|
|
* @param {port} [h_port]
|
|
* @param {privat} [h_priv]
|
|
* @param {Command} [h_command]
|
|
* @param {(Status.STD_OK|*)} [h_status]
|
|
* @returns {header}
|
|
*/
|
|
|
|
function Header(h_port,h_priv,h_command,h_status) {
|
|
var obj = new header(h_port,h_priv,h_command,h_status);
|
|
Object.preventExtensions(obj);
|
|
return obj;
|
|
}
|
|
|
|
/*
|
|
** Hash table of all locally created unique ports.
|
|
*/
|
|
var uniqports=[];
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
var Net = {
|
|
// Direction:Direction,
|
|
PORT_SIZE:PORT_SIZE,
|
|
PRIV_SIZE:PRIV_SIZE,
|
|
|
|
AFS_REQBUFSZ:AFS_REQBUFSZ,
|
|
CAP_SIZE:CAP_SIZE,
|
|
DNS_MAXCOLUMNS:DNS_MAXCOLUMNS,
|
|
TIMEOUT:5000,
|
|
DEF_RPC_MAX_HOP:DEF_RPC_MAX_HOP,
|
|
|
|
Status:Status,
|
|
Command:Command,
|
|
Rights:Rights,
|
|
|
|
Private:Private,
|
|
Capability: Capability,
|
|
Header: Header,
|
|
Port: port,
|
|
|
|
/**
|
|
* @type {port}
|
|
*/
|
|
nilport: port(),
|
|
nilpriv: Private(0,0,this.nilport),
|
|
nilcap: Capability(this.nilport,this.nilpriv),
|
|
|
|
/*
|
|
** Utils to get and set single bytes of a port
|
|
*/
|
|
get_portbyte: function(port,i) {
|
|
return Perv.int_of_char(String.get(port,i))
|
|
},
|
|
set_portbyte: function(port,i,byte) {
|
|
return String.set(port, i, (Perv.char_of_int(byte)));
|
|
},
|
|
/*
|
|
* Return a unique key of a capability that can be used for hash tables
|
|
*/
|
|
key: function (cap) {
|
|
return cap.cap_port+
|
|
cap.cap_priv.prv_obj+
|
|
cap.cap_priv.prv_rights+
|
|
cap.cap_priv.prv_rand;
|
|
},
|
|
|
|
/*
|
|
** Encryption function
|
|
*/
|
|
one_way: function (port) {
|
|
var key = Array.create(64,0);
|
|
var block = Array.create(48,0);
|
|
var pubport = String.make (PORT_SIZE,'\0');
|
|
var i, j, k;
|
|
|
|
/*
|
|
** We actually need 64 bit key.
|
|
** Throw some zeroes in at bits 6 and 7 mod 8
|
|
** The bits at 7 mod 8 etc are not used by the algorithm
|
|
*/
|
|
j=0;
|
|
for (i = 0; i< 64; i++) {
|
|
if ((i & 7) > 5)
|
|
key[i] = 0;
|
|
else {
|
|
if ((this.get_portbyte(port, (j >> 3)) & (1 << (j & 7))) != 0)
|
|
key[i] = 1;
|
|
else
|
|
key[i] = 0;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
Des48.des_OWsetkey(key);
|
|
/*
|
|
** Now go encrypt constant 0
|
|
*/
|
|
block=Des48.des_OWcrypt48(block);
|
|
|
|
|
|
/*
|
|
** and put the bits in the destination port
|
|
*/
|
|
var pb = 0;
|
|
|
|
for (i = 0; i < PORT_SIZE;i++) {
|
|
var pbyte = 0;
|
|
for (j = 0; j < 8; j++) {
|
|
pbyte = pbyte | (block[pb] << j);
|
|
pb++;
|
|
}
|
|
pubport=this.set_portbyte(pubport, i, pbyte);
|
|
}
|
|
|
|
return pubport;
|
|
},
|
|
/*
|
|
** Check whether the required rights [R1;R2;..] are
|
|
** present in the rights field rg. Return a boolean value.
|
|
*/
|
|
rights_req : function(rights,required) {
|
|
var all=true;
|
|
Array.iter(required,function(rq) {
|
|
if (rq & rights == 0) all = false;
|
|
});
|
|
return all;
|
|
},
|
|
port_cmp: function(port1,port2) {
|
|
var i;
|
|
var eq=true;
|
|
for(i=0;i<PORT_SIZE;i++) { if (String.get(port1,i)!=String.get(port2,i)) eq=false;}
|
|
return eq;},
|
|
port_copy: function(port) {
|
|
return String.copy(port);
|
|
},
|
|
/*
|
|
** Derive a port from a string.
|
|
*/
|
|
port_name: function(name){
|
|
var p = String.make(PORT_SIZE,'\0');
|
|
var i;
|
|
var n = name.length;
|
|
|
|
for (i = 0; i < n;i++) {
|
|
var k = i % PORT_SIZE;
|
|
p = String.set(p, k, Perv.char_of_int(
|
|
(Perv.int_of_char(String.get(p, k)) +
|
|
Perv.int_of_char(String.get(name, i)))
|
|
& 0xff));
|
|
}
|
|
return p;
|
|
},
|
|
port_to_str: function(port,compact) {
|
|
var i,str='';
|
|
if (port) {
|
|
for (i = 0; i < PORT_SIZE; i++) {
|
|
var num = Perv.int_of_char(String.get(port, i));
|
|
if (!compact && i > 0) str = str + ':';
|
|
str = str + pad(num.toString(16).toUpperCase(), 2);
|
|
}
|
|
} else str='undefined';
|
|
return str;
|
|
},
|
|
port_of_str: function (str,compact) {
|
|
var tokens=str.split(':'),i,port='';
|
|
for (i=0;i<PORT_SIZE;i++) {
|
|
var num='0x'+tokens[i];
|
|
port=port+Perv.char_of_int(parseInt(num,16));
|
|
}
|
|
return port;
|
|
},
|
|
/** String parameter to port conversion including "undefined" case.
|
|
*
|
|
* @param str
|
|
* @returns {string}
|
|
*/
|
|
port_of_param: function (str) {
|
|
if (str==undefined ||
|
|
String.equal(str,'undefined')) return undefined;
|
|
var tokens=str.split(':');
|
|
var i;
|
|
var port='';
|
|
for (i=0;i<PORT_SIZE;i++) {
|
|
var num='0x'+tokens[i];
|
|
port=port+Perv.char_of_int(parseInt(num,16));
|
|
}
|
|
return port;
|
|
},
|
|
prv2pub: function(port) {
|
|
var putport;
|
|
if (priv2pub_cache[port] == undefined) {
|
|
putport=this.one_way(port);
|
|
priv2pub_cache[port] = putport;
|
|
} else putport = priv2pub_cache[port];
|
|
return putport;
|
|
},
|
|
/**
|
|
** Decode a private structure
|
|
*
|
|
* @param {privat} prv
|
|
* @param {port} rand
|
|
* @returns {boolean}
|
|
*/
|
|
prv_decode: function(prv,rand) {
|
|
if (prv.prv_rights == Rights.PRV_ALL_RIGHTS)
|
|
return this.port_cmp(prv.prv_rand,rand);
|
|
else {
|
|
var tmp_port = this.port_copy(rand),
|
|
pt0 = this.get_portbyte(tmp_port, 0),
|
|
pr0 = prv.prv_rights;
|
|
tmp_port = this.set_portbyte(tmp_port, 0, (pt0 ^ pr0));
|
|
tmp_port = this.one_way(tmp_port);
|
|
return this.port_cmp(prv.prv_rand, tmp_port)
|
|
}
|
|
},
|
|
/*
|
|
** Encode a private part from the object number, the rights field
|
|
** and the random port.
|
|
** Returns the created private structure.
|
|
*/
|
|
prv_encode: function(obj,rights,rand) {
|
|
var tmp_port = this.port_copy(rand);
|
|
|
|
var r1 = rights;
|
|
var rmask = Rights.PRV_ALL_RIGHTS;
|
|
|
|
if (rights == Rights.PRV_ALL_RIGHTS)
|
|
return this.Private(obj,r1 & rmask,tmp_port);
|
|
else {
|
|
var pt0 = this.get_portbyte(tmp_port,0);
|
|
tmp_port = this.set_portbyte(tmp_port,0,pt0 ^ r1);
|
|
tmp_port = this.one_way(tmp_port);
|
|
return this.Private(obj,r1 & rmask,tmp_port)
|
|
}
|
|
},
|
|
/*
|
|
** Return the private object number form a private structure
|
|
*/
|
|
prv_number: function(prv) {
|
|
return prv.prv_obj;
|
|
},
|
|
/*
|
|
** Return the private rights field.
|
|
*/
|
|
prv_rights: function(prv) {
|
|
return prv.prv_rights & Rights.PRV_ALL_RIGHTS;
|
|
},
|
|
|
|
/*
|
|
** Check the private rights field: 1. Validation, 2: Required rights.
|
|
*/
|
|
prv_rights_check: function(prv,rand,required) {
|
|
if (!Net.prv_decode(prv,rand)) return false;
|
|
return (prv.prv_rights & required)==required;
|
|
},
|
|
|
|
/** Restrict a private field (rights&mask) of a capability.
|
|
*
|
|
* @param {privat} priv
|
|
* @param {number} mask rights restriction mask
|
|
* @param {port} random secret server random port
|
|
*/
|
|
restrict: function(priv,mask,random) {
|
|
var pr =
|
|
this.prv_encode(priv.prv_obj,
|
|
priv.prv_rights & mask,
|
|
random);
|
|
return pr;
|
|
},
|
|
/*
|
|
* Return a new random port.
|
|
*
|
|
* Warning: the quality of the random ports are strongly
|
|
* related to JSVMs underlying random generator. Be warned!
|
|
*
|
|
* @returns {port}
|
|
*/
|
|
uniqport: function() {
|
|
var port = String.create (PORT_SIZE);
|
|
var exists = true;
|
|
while (exists) {
|
|
var i;
|
|
for (i = 0; i <= (PORT_SIZE - 1); i++) {
|
|
|
|
port = String.set(port, i, (Perv.char_of_int(Rand.int(256))));
|
|
}
|
|
if (uniqports[port]==undefined)
|
|
{
|
|
uniqports[port]=port;
|
|
exists=false;
|
|
}
|
|
}
|
|
return port;
|
|
},
|
|
/** Write a capability to a file.
|
|
*
|
|
* @param {capability} cap
|
|
* @param {string} path
|
|
*/
|
|
cap_to_file: function(cap,path) {
|
|
try {
|
|
Fs.writeFileSync(path, this.Print.capability(cap));
|
|
} catch(e) {
|
|
}
|
|
},
|
|
/** Read a capability from a file.
|
|
*
|
|
* @param {string} path
|
|
* @returns {capability|undefined}
|
|
*/
|
|
cap_of_file: function(path) {
|
|
try {
|
|
var cap=undefined;
|
|
var data = Fs.readFileSync(path);
|
|
var cp = this.Parse.capability(data.toString(), 0);
|
|
cap = cp.cap;
|
|
return cap;
|
|
} catch(e) {
|
|
return undefined;
|
|
}
|
|
},
|
|
|
|
Position: function (x,y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
},
|
|
Copy: {
|
|
/**
|
|
*
|
|
* @param src
|
|
* @returns {port}
|
|
*/
|
|
port: function(src) {
|
|
// !!!!
|
|
return String.copy(src);
|
|
},
|
|
/**
|
|
*
|
|
* @param src
|
|
* @param dst
|
|
* @returns {privat}
|
|
*/
|
|
private: function(src,dst) {
|
|
if (dst!=undefined) {
|
|
dst.prv_obj = src.prv_obj;
|
|
dst.prv_rights = src.prv_rights;
|
|
dst.prv_rand = this.port(src.prv_rand);
|
|
return dst;
|
|
} else {
|
|
var dstnew=Private();
|
|
dstnew.prv_obj = src.prv_obj;
|
|
dstnew.prv_rights = src.prv_rights;
|
|
dstnew.prv_rand = this.port(src.prv_rand);
|
|
return dstnew;
|
|
}
|
|
},
|
|
/**
|
|
*
|
|
* @param src
|
|
* @param dst
|
|
* @returns {capability}
|
|
*/
|
|
capability: function(src,dst) {
|
|
if (dst!=undefined) {
|
|
dst.cap_port = this.port(src.cap_port);
|
|
this.private(src.cap_priv, dst.cap_priv);
|
|
return dst;
|
|
}
|
|
else {
|
|
var dstnew=Capability();
|
|
dstnew.cap_port = this.port(src.cap_port);
|
|
this.private(src.cap_priv, dstnew.cap_priv);
|
|
return dstnew;
|
|
}
|
|
},
|
|
/**
|
|
*
|
|
* @param src
|
|
* @param dst
|
|
*/
|
|
header: function(src,dst) {
|
|
dst.h_port=this.port(src.h_port);
|
|
dst.h_status=src.h_status;
|
|
dst.h_command=src.h_command;
|
|
if (src.h_priv!=undefined) {
|
|
if (dst.h_priv==undefined) {
|
|
var obj = new privat();
|
|
Object.preventExtensions(obj);
|
|
dst.h_priv=obj;
|
|
}
|
|
this.private(src.h_priv,dst.h_priv);
|
|
} else dst.h_priv=undefined;
|
|
}
|
|
},
|
|
Equal: {
|
|
port: function (port1,port2) {
|
|
if (port1==undefined || port2==undefined) return (port1==port2);
|
|
else return String.equal(port1,port2);
|
|
},
|
|
private: function (prv1,prv2) {
|
|
return (prv1==undefined&&prv2==undefined) ||
|
|
(prv1.prv_obj==prv2.prv_obj &&
|
|
prv1.prv_rights==prv2.prv_rights &&
|
|
this.port(prv1.prv_rand,prv2.prv_rand))
|
|
},
|
|
capability: function(cap1,cap2) {
|
|
return (cap1==undefined&&cap2==undefined) ||
|
|
(this.private(cap1.cap_priv,cap2.cap_priv) &&
|
|
this.port(cap1.cap_port,cap2.cap_port))
|
|
},
|
|
header: function(hdr1,hdr2) {
|
|
return (hdr1==undefined&&hdr2==undefined) ||
|
|
(this.private(hdr1.h_priv,hdr1.h_priv) &&
|
|
this.port(hdr1.h_port,hdr2.h_port) &&
|
|
hdr1.h_status==hdr2.h_status &&
|
|
hdr1.h_command==hdr2.h_command)
|
|
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @typedef {{
|
|
* port:function(string,number):{port:port,pos:number}|undefined,
|
|
* private:function(string,number):{priv:privat,pos:number}|undefined,
|
|
* capability:function(string,number):{cap:capability,pos:number}|undefined
|
|
* }} Parse
|
|
*/
|
|
Parse: {
|
|
/**
|
|
*
|
|
* @param str
|
|
* @param pos
|
|
* @returns {{port:port,pos:number}}
|
|
*/
|
|
port: function(str,pos) {
|
|
var port='';
|
|
var len=str.length;
|
|
if (pos==undefined) pos=0;
|
|
if (len<(pos+17)) return undefined;
|
|
if (str[pos]=='[') pos++;
|
|
for(var i=0;i<6;i++) {
|
|
var sv='0x'+str[pos]+str[pos+1];
|
|
port=port+Perv.char_of_int(Perv.int_of_string(sv));
|
|
pos=pos+2;
|
|
if (str[pos]==':') pos++;
|
|
}
|
|
if (str[pos]==']') pos++;
|
|
return {port:port,pos:pos};
|
|
},
|
|
/**
|
|
*
|
|
* @param str
|
|
* @param pos
|
|
* @returns {{priv:privat,pos:number}}
|
|
*/
|
|
private: function(str,pos) {
|
|
var priv=Private();
|
|
var sv;
|
|
var len=str.length;
|
|
if (pos==undefined) pos=0;
|
|
if (len<(pos+25)) return undefined;
|
|
if (str[pos]=='(') pos++;
|
|
sv='';
|
|
while(str[pos]!='(') {
|
|
sv=sv+str[pos];
|
|
pos++;
|
|
}
|
|
priv.prv_obj=Perv.int_of_string(sv);
|
|
sv='';
|
|
if (str[pos]=='(') pos++;
|
|
while(str[pos]!=')') {
|
|
sv=sv+str[pos];
|
|
pos++;
|
|
}
|
|
priv.prv_rights=Perv.int_of_string('0x'+sv);
|
|
if (str[pos]==')') pos++;
|
|
var pp=this.port(str,pos);
|
|
if (pp==undefined) return undefined;
|
|
priv.prv_rand=pp.port;
|
|
pos=pp.pos;
|
|
return {priv:priv,pos:pos};
|
|
},
|
|
/**
|
|
*
|
|
* @param str
|
|
* @param pos
|
|
* @returns {{cap:capability,pos:number}|undefined}
|
|
*/
|
|
capability: function(str,pos) {
|
|
var cap=Capability();
|
|
if (pos==undefined) pos=0;
|
|
var pp=this.port(str,pos);
|
|
if (pp==undefined) return undefined;
|
|
cap.cap_port=pp.port;
|
|
pos=pp.pos;
|
|
pp=this.private(str,pos);
|
|
if (pp==undefined) return undefined;
|
|
cap.cap_priv=pp.priv;
|
|
pos=pp.pos;
|
|
return {cap:cap,pos:pos};
|
|
}
|
|
},
|
|
Print: {
|
|
/**
|
|
*
|
|
* @param cap
|
|
* @returns {string}
|
|
*/
|
|
capability: function (cap) {
|
|
var str='';
|
|
if (cap==undefined) return 'undefined';
|
|
if (cap.cap_port!=undefined) str='['+this.port(cap.cap_port)+']'; else str = '[]';
|
|
if (cap.cap_priv!=undefined) str=str+'('+this.private(cap.cap_priv)+')'; else str=str+'()';
|
|
return str;
|
|
},
|
|
command: Command.print,
|
|
/**
|
|
*
|
|
* @param hdr
|
|
* @returns {string}
|
|
*/
|
|
header: function (hdr) {
|
|
var str='';
|
|
if (hdr==undefined) return 'undefined';
|
|
if (hdr.h_port!=undefined) str='['+this.port(hdr.h_port)+']'; else str = '[]';
|
|
if (hdr.h_command!=undefined) str=str+': '+Command.print(hdr.h_command);
|
|
if (hdr.h_priv!=undefined) str=str+'('+this.private(hdr.h_priv)+')'; else str=str+'()';
|
|
if (hdr.h_status!=undefined) str=str+' ?'+Status.print(hdr.h_status);
|
|
return str;
|
|
},
|
|
/**
|
|
*
|
|
* @param port
|
|
* @returns {string}
|
|
*/
|
|
port: function(port) {
|
|
var i;
|
|
var str='';
|
|
if (port!=undefined) {
|
|
for (i = 0; i < PORT_SIZE; i++) {
|
|
var num = Perv.int_of_char(String.get(port, i));
|
|
if (i > 0) str = str + ':';
|
|
str = str + pad(num.toString(16).toUpperCase(), 2);
|
|
}
|
|
} else str='undefined';
|
|
return str;
|
|
},
|
|
/**
|
|
*
|
|
* @param priv
|
|
* @returns {string}
|
|
*/
|
|
private: function(priv) {
|
|
var str='';
|
|
if (priv==undefined) return 'undefined';
|
|
str=priv.prv_obj;
|
|
str=str+'('+String.format_hex(priv.prv_rights,2).toUpperCase()+')[';
|
|
str=str+this.port(priv.prv_rand)+']';
|
|
return str;
|
|
},
|
|
status: Status.print
|
|
}
|
|
};
|
|
|
|
module.exports = Net;
|