diff --git a/demo/chat/chat.js b/demo/chat/chat.js index dcf647c..a5a97b9 100644 --- a/demo/chat/chat.js +++ b/demo/chat/chat.js @@ -4,6 +4,7 @@ import { createRequire } from 'module' import AsyncReply from "../../src/Core/AsyncReply.js"; import DistributedServer from "../../src/Net/IIP/DistributedServer.js"; import IMembership from "../../src/Security/Membership/IMembership.js"; +import AuthorizationResults from "../../src/Security/Membership/AuthorizationResults.js"; import WSocket from "../../src/Net/Sockets/WSocket.js"; import MemoryStore from "../../src/Stores/MemoryStore.js"; import DC from "../../src/Data/DC.js"; @@ -13,6 +14,12 @@ import TypedMap from "../../src/Data/TypedMap.js"; import { Arg, Evt, Func, Prop, TemplateDescriber } from "../../src/Resource/Template/TemplateDescriber.js"; import { Int32 } from "../../src/Data/ExtendedTypes.js"; +import AuthorizationResultsResponse from "../../src/Security/Membership/AuthorizationResultsResponse.js"; +import IIPAuthPacketIAuthDestination from '../../src/Net/Packets/IIPAuthPacketIAuthDestination.js'; +import IIPAuthPacketIAuthFormat from '../../src/Net/Packets/IIPAuthPacketIAuthFormat.js'; +import IIPAuthPacketHeader from '../../src/Net/Packets/IIPAuthPacketHeader.js'; +import Codec from '../../src/Data/Codec.js'; + const require = createRequire(import.meta.url); @@ -31,6 +38,64 @@ class MyMembership extends IMembership { getPassword(username, domain) { return new AsyncReply(DC.stringToBytes("1234")); } + + authorize(session){ + + let results = new AuthorizationResults(); + + if (session.authorizedAccount == "admin") + { + results.clue = "What is 5 + 2 ?"; + results.destination = IIPAuthPacketIAuthDestination.Self; + results.requiredFormat = IIPAuthPacketIAuthFormat.Number; + results.response = AuthorizationResultsResponse.IAuthHashed; + results.expire = new Date(new Date().getTime() + 30000); + results.reference = Math.round(Math.random() * 100000); + } + else if (session.authorizedAccount == "demo") + { + results.clue = "What is 10 * 2 ?"; + results.destination = IIPAuthPacketIAuthDestination.Self; + results.requiredFormat = IIPAuthPacketIAuthFormat.Number; + results.response = AuthorizationResultsResponse.IAuthPlain; + results.expire = new Date(new Date().getTime() + 30000); + results.reference = Math.round(Math.random() * 100000); + } + else { + results.response = AuthorizationResultsResponse.Success; + } + + return new AsyncReply(results); + } + + authorizeHashed(session, reference, algorithm, value){ + + // compute hash + let remoteNonce = session.remoteHeaders.get(IIPAuthPacketHeader.Nonce); + let localNonce = session.localHeaders.get(IIPAuthPacketHeader.Nonce); + + var hashFunc = SHA256.Create(); + // local nonce + password or token + remote nonce + var challenge = hashFunc.ComputeHash(new BinaryList() + .addUint8Array(remoteNonce) + .addUint8Array(Codec.compose(7, null)) // answer is 7 + .addUint8Array(localNonce) + .toArray()); + + if (challenge.sequenceEqual(value)) + return new AsyncReply(new AuthorizationResults(AuthorizationResultsResponse.Success)); + else + return new AsyncReply(new AuthorizationResults(AuthorizationResultsResponse.Failed)); + + } + + authorizePlain(session, reference, value) { + if (value == 20) + return new AsyncReply(new AuthorizationResults(AuthorizationResultsResponse.Success)); + else + return new AsyncReply(new AuthorizationResults(AuthorizationResultsResponse.Failed)); + } + }; var server; @@ -53,12 +118,12 @@ class MyChat extends IResource { } get users() { - return server.connections.map(x=>x.session.remoteAuthentication.username); + return server.connections.map(x=>x.session.authorizedAccount); } send(msg, sender) { - let s = new TypedMap({ msg, usr: sender.session.remoteAuthentication.username, date: new Date()}); + let s = new TypedMap({ msg, usr: sender.session.authorizedAccount, date: new Date()}); this.messages.push(s); this._emit("message", s); } diff --git a/demo/chat/index.html b/demo/chat/index.html index 7dfaff3..d308a1f 100644 --- a/demo/chat/index.html +++ b/demo/chat/index.html @@ -6,6 +6,15 @@ var service; let $ = document.querySelector; + function authenticator(x) + { + debugger; + let challenge = prompt(x.clue); + if (challenge != null) { + return new Esiur.Core.AsyncReply(parseInt(challenge)); + } + } + async function connect(){ let status = document.getElementById("status"); @@ -15,7 +24,7 @@ try { status.innerHTML = "Connecting..."; - service = await wh.get("iip://localhost:8001/chat", {username, password: "1234", autoReconnect: true}); + service = await wh.get("iip://localhost:8001/sys/chat", {username, password: "1234", autoReconnect: true, authenticator: authenticator}); login.style.display = "none"; service.on("message", appendMessage) .on(":title", updateTitle) diff --git a/src/Misc/Global.js b/src/Misc/Global.js new file mode 100644 index 0000000..1b4bbca --- /dev/null +++ b/src/Misc/Global.js @@ -0,0 +1,22 @@ + +export default class Global +{ + static generateBytes(length){ + var rt = new Uint8Array(length); + for (var i = 0; i < length; i++) + rt[i] = Math.random() * 255; + + return rt; + } + + static generateCode(length = 16) { + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let rt = ""; + + for (var i = 0; i < length; i++) + rt += chars[Math.round(Math.random() * chars.length)]; + + return rt; + } + +} \ No newline at end of file diff --git a/src/Net/IIP/DistributedConnection.js b/src/Net/IIP/DistributedConnection.js index a32df96..72ebc19 100644 --- a/src/Net/IIP/DistributedConnection.js +++ b/src/Net/IIP/DistributedConnection.js @@ -91,6 +91,11 @@ import { UInt8 } from '../../Data/ExtendedTypes.js'; import ConnectionStatus from './ConnectionStatus.js'; import { Prop, TemplateDescriber } from '../../Resource/Template/TemplateDescriber.js'; import TypedMap from '../../Data/TypedMap.js'; +import Global from '../../Misc/Global.js'; +import IIPAuthPacketHashAlgorithm from '../../Net/Packets/IIPAuthPacketHashAlgorithm.js'; +import AuthorizationResultsResponse from '../../Security/Membership/AuthorizationResultsResponse.js'; +import IIPAuthPacketIAuthHeader from '../../Net/Packets/IIPAuthPacketIAuthHeader.js'; +import AuthorizationRequest from '../../Security/Membership/AuthorizationRequest.js'; export default class DistributedConnection extends IStore { @@ -100,7 +105,7 @@ export default class DistributedConnection extends IStore { #secure; #socket; - #lastKeepAliveSent + #lastKeepAliveSent; #lastKeepAliveReceived; #status; @@ -123,7 +128,9 @@ export default class DistributedConnection extends IStore { #loginDate; - jitter = 0; + #jitter = 0; + + keepAliveTime = 10; keepAliveInterval = 30; @@ -144,6 +151,10 @@ export default class DistributedConnection extends IStore { #subscriptions = new Map(); #ready; + get jitter() { + return this.#jitter; + } + get session() { return this.#session; } @@ -160,13 +171,9 @@ export default class DistributedConnection extends IStore { return new SendList(this, doneReply); } - #generateCode(length) { - var rt = new Uint8Array(length); - for (var i = 0; i < length; i++) - rt[i] = Math.random() * 255; - return rt; - } + + constructor(server) { @@ -174,7 +181,8 @@ export default class DistributedConnection extends IStore { this.#session.authenticationType = AuthenticationType.Host; this.#session.localMethod = AuthenticationMethod.None; - + this.#session.localHeaders.set(IIPAuthPacketHeader.Nonce, Global.generateBytes(32)); + this.#server = server; this._register("ready"); @@ -192,6 +200,9 @@ export default class DistributedConnection extends IStore { } }); + // set local nonce + + } @@ -636,7 +647,7 @@ export default class DistributedConnection extends IStore { } // start perodic keep alive timer - this.#keepAliveTimer = setInterval(this.#keepAliveTimerElapsed, this.keepAliveInterval * 1000); + this.#keepAliveTimer = setInterval(this.#keepAliveTimerElapsed.bind(this), this.keepAliveInterval * 1000); } else if (authPacket.event == IIPAuthPacketEvent.IAuthPlain) @@ -644,7 +655,8 @@ export default class DistributedConnection extends IStore { let dataType = authPacket.dataType; let pr = Codec.parse(data, dataType.offset, this, null, dataType); let headers = pr.reply.result; - + let iAuthRequest = new AuthorizationRequest(headers); + if (authenticator == null) { @@ -657,16 +669,15 @@ export default class DistributedConnection extends IStore { } else { - this.authenticator(headers).then((response) => + this.authenticator(iAuthRequest).then((response) => { this.#sendParams() .addUint8(IIPAuthPacketAction.IAuthPlain) - .addUint32(headers[IIPAuthPacketIAuthHeader.Reference]) + .addUint32(headers.get(IIPAuthPacketIAuthHeader.Reference)) .addDC(Codec.compose(response, this)) .done(); }) - .timeout(headers.containsKey(IIPAuthPacketIAuthHeader.Timeout) ? - headers[IIPAuthPacketIAuthHeader.Timeout] * 1000 : 30000, + .timeout(iAuthRequest.timeout * 1000, () => { this.#sendParams() .addUint8(IIPAuthPacketEvent.ErrorTerminate) @@ -683,7 +694,8 @@ export default class DistributedConnection extends IStore { let dataType = authPacket.dataType; let parsed = Codec.parse(data, dataType.offset, this, null, dataType); let headers = parsed.reply.result; - + let iAuthRequest = new AuthorizationRequest(headers); + if (this.authenticator == null) { this.#sendParams() @@ -695,7 +707,7 @@ export default class DistributedConnection extends IStore { } else { - this.authenticator(headers).then((response) => + this.authenticator(iAuthRequest).then((response) => { var hash = SHA256.compute((BL() @@ -706,14 +718,13 @@ export default class DistributedConnection extends IStore { this.#sendParams() .addUint8(IIPAuthPacketAction.IAuthHashed) - .addUint32(headers[IIPAuthPacketIAuthHeader.Reference]) + .addUint32(headers.get(IIPAuthPacketIAuthHeader.Reference)) .addUint8(IIPAuthPacketHashAlgorithm.SHA256) .addUint16(hash.length) .addDC(hash) .done(); }) - .timeout(headers.containsKey(IIPAuthPacketIAuthHeader.Timeout) ? - headers[IIPAuthPacketIAuthHeader.Timeout] * 1000 : 30000, + .timeout(iAuthRequest.timeout * 1000, () => { this.#sendParams() .addUint8(IIPAuthPacketEvent.ErrorTerminate) @@ -880,7 +891,7 @@ export default class DistributedConnection extends IStore { { let localHeaders = session.localHeaders; - session.authorizedAccount = "g-" + this.#generateCode(); + session.authorizedAccount = "g-" + Global.generateCode(); this.#readyToEstablish = true; @@ -1067,20 +1078,14 @@ export default class DistributedConnection extends IStore { { if (results == null || results.response == AuthorizationResultsResponse.Success) { - - var r = new Random(); - var n = new DC(32); - for (var i = 0; i < 32; i++) - n[i] = r.nextInt(255); + this.#session.id = Global.generateCode(32); - session.id = n; - - let accountId = DC.stringToBytes(session.authorizedAccount); + let accountId = DC.stringToBytes(this.#session.authorizedAccount); this.#sendParams() .addUint8(IIPAuthPacketEvent.IndicationEstablished) - .addUint8(n.length) - .addUint8Array(n) + .addUint8(this.#session.id.length) + .addUint8Array(this.#session.id) .addUint8(accountId.length) .addUint8Array(accountId) .done(); @@ -1095,7 +1100,7 @@ export default class DistributedConnection extends IStore { this.#openReply = null; this._emit("ready", this); - this.#server?.membership?.login(session); + this.#server?.membership?.login(this.#session); this.#loginDate = new Date(); }).error((x) => @@ -1146,11 +1151,11 @@ export default class DistributedConnection extends IStore { } else if (results.response == AuthorizationResultsResponse.IAuthPlain) { - var args = new (TypedMap.of(Number, Object))([ + var args = new (TypedMap.of(UInt8, Object))([ [IIPAuthPacketIAuthHeader.Reference, results.reference], [IIPAuthPacketIAuthHeader.Destination, results.destination], - [IIPAuthPacketIAuthHeader.Timeout, results.timeout], + [IIPAuthPacketIAuthHeader.Expire, results.expire], [IIPAuthPacketIAuthHeader.Clue, results.clue], [IIPAuthPacketIAuthHeader.RequiredFormat, results.requiredFormat], ]); @@ -1167,7 +1172,7 @@ export default class DistributedConnection extends IStore { [IIPAuthPacketIAuthHeader.Reference, results.reference], [IIPAuthPacketIAuthHeader.Destination, results.destination], - [IIPAuthPacketIAuthHeader.Timeout, results.timeout], + [IIPAuthPacketIAuthHeader.Expire, results.expire], [IIPAuthPacketIAuthHeader.Clue, results.clue], [IIPAuthPacketIAuthHeader.RequiredFormat, results.requiredFormat], ]); @@ -1184,7 +1189,7 @@ export default class DistributedConnection extends IStore { [IIPAuthPacketIAuthHeader.Reference, results.reference], [IIPAuthPacketIAuthHeader.Destination, results.destination], - [IIPAuthPacketIAuthHeader.Timeout, results.timeout], + [IIPAuthPacketIAuthHeader.Expire, results.expire], [IIPAuthPacketIAuthHeader.Clue, results.clue], [IIPAuthPacketIAuthHeader.RequiredFormat, results.requiredFormat], ]); @@ -1345,9 +1350,11 @@ export default class DistributedConnection extends IStore { autoReconnect = false, keepAliveInterval = 30, keepAliveTime = 10, - reconnectInterval = 5} = this.instance.attributes.toObject(); + reconnectInterval = 5, + authenticator = null} = this.instance.attributes.toObject(); + this.authenticator = authenticator; this.debug = debug; this.checkInterval = checkInterval * 1000; // check every 30 seconds this.connectionTimeout = connectionTimeout * 1000; // 10 minutes (4 pings failed) @@ -1402,7 +1409,7 @@ export default class DistributedConnection extends IStore { this.#session.remoteMethod = AuthenticationMethod.None; this.#session.localHeaders.set(IIPAuthPacketHeader.Domain, domain); - this.#session.localHeaders.set(IIPAuthPacketHeader.Nonce, this.#generateCode(32)); + this.#session.localHeaders.set(IIPAuthPacketHeader.Nonce, Global.generateBytes(32)); if (method == AuthenticationMethod.Credentials) { @@ -1682,11 +1689,14 @@ export default class DistributedConnection extends IStore { var reply = new AsyncReply(); this.#callbackCounter++; this.#requests.set(this.#callbackCounter, reply); - return this.this.#sendParams(reply).addUint8(0x40 | action).addUint32(this.#callbackCounter); + return this.#sendParams(reply) + .addUint8(0x40 | action) + .addUint32(this.#callbackCounter); } - async detachResource(instanceId){ + _sendDetachRequest(instanceId) + { try { if (this.#attachedResources.containsKey(instanceId)) @@ -1695,19 +1705,9 @@ export default class DistributedConnection extends IStore { if (this.#suspendedResources.containsKey(instanceId)) this.#suspendedResources.remove(instanceId); - await this.#sendDetachRequest(instanceId); - } - catch - { - - } - } - - #sendDetachRequest(instanceId) - { - try - { - return this.#sendRequest(IIPPacketAction.DetachResource).addUint32(instanceId).done(); + return this.#sendRequest(IIPPacketAction.DetachResource) + .addUint32(instanceId) + .done(); } catch(ex) { @@ -1715,13 +1715,14 @@ export default class DistributedConnection extends IStore { } } - #sendInvoke(instanceId, index, parameters) { + _sendInvoke(instanceId, index, parameters) { + var reply = new AsyncReply(); var pb = Codec.compose(parameters, this); let callbackId = ++this.#callbackCounter; - this.this.#sendParams() + this.#sendParams() .addUint8(0x40 | IIPPacketAction.InvokeFunction) .addUint32(callbackId) .addUint32(instanceId) @@ -1734,17 +1735,28 @@ export default class DistributedConnection extends IStore { return reply; } + _sendSetProperty(instanceId, index, value){ + + var cv = Codec.compose(value, this); + + return this.#sendRequest(IIPPacketAction.SetProperty) + .addUint32(instanceId) + .addUint8(index) + .addUint8Array(cv) + .done() + } + #sendError(type, callbackId, errorCode, errorMessage = "") { var msg = DC.stringToBytes(errorMessage); if (type == ErrorType.Management) - this.this.#sendParams() + this.#sendParams() .addUint8(0xC0 | IIPPacketReport.ManagementError) .addUint32(callbackId) .addUint16(errorCode) .done(); else if (type == ErrorType.Exception) - this.this.#sendParams() + this.#sendParams() .addUint8(0xC0 | IIPPacketReport.ExecutionError) .addUint32(callbackId) .addUint16(errorCode) @@ -1754,7 +1766,7 @@ export default class DistributedConnection extends IStore { } #sendProgress(callbackId, value, max) { - this.this.#sendParams() + this.#sendParams() .addUint8(0xC0 | IIPPacketReport.ProgressReport) .addUint32(callbackId) .addInt32(value) @@ -1764,7 +1776,7 @@ export default class DistributedConnection extends IStore { #sendChunk(callbackId, chunk) { var c = Codec.compose(chunk, this); - this.this.#sendParams() + this.#sendParams() .addUint8(0xC0 | IIPPacketReport.ChunkStream) .addUint32(callbackId) .addUint8Array(c) @@ -1851,12 +1863,12 @@ export default class DistributedConnection extends IStore { // push to the queue to gaurantee serialization let item = new AsyncReply(); - self.queue.add(item); + self.#queue.add(item); Codec.parse(data, 0, self, null, dataType).reply.then(function (args) { item.trigger(new DistributedResourceQueueItem(r, DistributedResourceQueueItemType.Propery, args, index)); }).error(function (ex) { - self.queue.remove(item); + self.#queue.remove(item); console.log("Esiur Property Error", ex); }); }); @@ -1874,14 +1886,14 @@ export default class DistributedConnection extends IStore { // push to the queue to guarantee serialization var item = new AsyncReply(); - self.queue.add(item); + self.#queue.add(item); // Codec.parseVarArray(content, 0, content.length, self).then(function (args) { Codec.parse(data, 0, self, null, dataType).reply.then(function (args) { item.trigger(new DistributedResourceQueueItem(r, DistributedResourceQueueItemType.Event, args, index)); }).error(function (ex) { - self.queue.remove(item); + self.#queue.remove(item); console.log("Esiur Event Error", ex); }); }); @@ -1927,19 +1939,19 @@ export default class DistributedConnection extends IStore { } #sendReply(action, callbackId) { - return this.this.#sendParams().addUint8(0x80 | action).addUint32(callbackId); + return this.#sendParams().addUint8(0x80 | action).addUint32(callbackId); } #sendEvent(evt) { - return this.this.#sendParams().addUint8(evt); + return this.#sendParams().addUint8(evt); } - #sendListenRequest(instanceId, index) + _sendListenRequest(instanceId, index) { var reply = new AsyncReply(); let callbackId = ++this.#callbackCounter; - this.this.#sendParams() + this.#sendParams() .addUint8(0x40 | IIPPacketAction.Listen) .addUint32(callbackId) .addUint32(instanceId) @@ -1951,12 +1963,12 @@ export default class DistributedConnection extends IStore { return reply; } - #sendUnlistenRequest(instanceId, index) + _sendUnlistenRequest(instanceId, index) { var reply = new AsyncReply(); let callbackId = ++this.#callbackCounter; - this.this.#sendParams() + this.#sendParams() .addUint8(0x40 | IIPPacketAction.Unlisten) .addUint32(callbackId) .addUint32(instanceId) @@ -1970,14 +1982,14 @@ export default class DistributedConnection extends IStore { IIPRequestAttachResource(callback, resourceId) { - //var sl = this.this.#sendParams(); + //var sl = this.#sendParams(); var self = this; Warehouse.getById(resourceId).then(function (r) { if (r != null) { - if (r.instance.applicable(self.session, ActionType.Attach, null) == Ruling.Denied) { + if (r.instance.applicable(self.#session, ActionType.Attach, null) == Ruling.Denied) { self.#sendError(ErrorType.Management, callback, ExceptionCode.AttachDenied); return; } @@ -2085,7 +2097,7 @@ export default class DistributedConnection extends IStore { } // check security - if (store.instance.applicable(self.session, ActionType.CreateResource, null) != Ruling.Allowed) { + if (store.instance.applicable(self.#session, ActionType.CreateResource, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.CreateDenied); return; } @@ -2095,7 +2107,7 @@ export default class DistributedConnection extends IStore { // check security if (parent != null) - if (parent.instance.applicable(self.session, ActionType.AddChild, null) != Ruling.Allowed) { + if (parent.instance.applicable(self.#session, ActionType.AddChild, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.AddChildDenied); return; } @@ -2396,7 +2408,7 @@ export default class DistributedConnection extends IStore { return; } - if (r.instance.applicable(self.session, ActionType.Execute, ft) == Ruling.Denied) { + if (r.instance.applicable(self.#session, ActionType.Execute, ft) == Ruling.Denied) { self.#sendError(ErrorType.Management, callback, ExceptionCode.InvokeDenied); return; } @@ -2655,12 +2667,11 @@ export default class DistributedConnection extends IStore { self.#sendReply(IIPPacketAction.SetProperty, callback) .done(); }).error(function (x) { - self.#sendError(x.type, callback, x.code, x.message) - .done(); + self.#sendError(x.type, callback, x.code, x.message); }); } else { - if (r.instance.applicable(self.session, ActionType.SetProperty, pt) == Ruling.Denied) { + if (r.instance.applicable(self.#session, ActionType.SetProperty, pt) == Ruling.Denied) { self.#sendError(AsyncReply.ErrorType.Exception, callback, ExceptionCode.SetPropertyDenied); return; } @@ -2673,7 +2684,7 @@ export default class DistributedConnection extends IStore { self.#sendReply(IIPPacketAction.SetProperty, callback).done(); } catch (ex) { - self.#sendError(AsyncReply.ErrorType.Exception, callback, 0, ex.toString()).done(); + self.#sendError(AsyncReply.ErrorType.Exception, callback, 0, ex.toString()); } } @@ -2681,12 +2692,12 @@ export default class DistributedConnection extends IStore { } else { // property not found - self.#sendError(AsyncReply.ErrorType.Management, callback, ExceptionCode.PropertyNotFound).done(); + self.#sendError(AsyncReply.ErrorType.Management, callback, ExceptionCode.PropertyNotFound); } } else { // resource not found - self.#sendError(AsyncReply.ErrorType.Management, callback, ExceptionCode.PropertyNotFound).done(); + self.#sendError(AsyncReply.ErrorType.Management, callback, ExceptionCode.PropertyNotFound); } }); } @@ -2714,7 +2725,7 @@ export default class DistributedConnection extends IStore { self.#sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound); else { - var list = resources.filter(function (r) { return r.instance.applicable(self.session, ActionType.Attach, null) != Ruling.Denied }); + var list = resources.filter(function (r) { return r.instance.applicable(self.#session, ActionType.Attach, null) != Ruling.Denied }); if (list.length == 0) self.#sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound); @@ -3148,12 +3159,12 @@ export default class DistributedConnection extends IStore { return; } - if (parent.instance.applicable(self.session, ActionType.AddChild, null) != Ruling.Allowed) { + if (parent.instance.applicable(self.#session, ActionType.AddChild, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.AddChildDenied); return; } - if (child.instance.applicable(self.session, ActionType.AddParent, null) != Ruling.Allowed) { + if (child.instance.applicable(self.#session, ActionType.AddParent, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.AddParentDenied); return; } @@ -3183,12 +3194,12 @@ export default class DistributedConnection extends IStore { return; } - if (parent.instance.applicable(self.session, ActionType.RemoveChild, null) != Ruling.Allowed) { + if (parent.instance.applicable(self.#session, ActionType.RemoveChild, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.AddChildDenied); return; } - if (child.instance.applicable(self.session, ActionType.RemoveParent, null) != Ruling.Allowed) { + if (child.instance.applicable(self.#session, ActionType.RemoveParent, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.AddParentDenied); return; } @@ -3211,7 +3222,7 @@ export default class DistributedConnection extends IStore { return; } - if (resource.instance.applicable(self.session, ActionType.Rename, null) != Ruling.Allowed) { + if (resource.instance.applicable(self.#session, ActionType.Rename, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.RenameDenied); return; } @@ -3262,7 +3273,7 @@ export default class DistributedConnection extends IStore { return; } - if (r.instance.store.instance.applicable(self.session, ActionType.UpdateAttributes, null) != Ruling.Allowed) { + if (r.instance.store.instance.applicable(self.#session, ActionType.UpdateAttributes, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.UpdateAttributeDenied); return; } @@ -3290,7 +3301,7 @@ export default class DistributedConnection extends IStore { return; } - if (r.instance.store.instance.applicable(self.session, ActionType.UpdateAttributes, null) != Ruling.Allowed) { + if (r.instance.store.instance.applicable(self.#session, ActionType.UpdateAttributes, null) != Ruling.Allowed) { self.#sendError(ErrorType.Management, callback, ExceptionCode.UpdateAttributeDenied); return; } @@ -3476,7 +3487,7 @@ export default class DistributedConnection extends IStore { .done() .then(x => { - self.jitter = x[1]; + self.#jitter = x[1]; self.#keepAliveTimer = setTimeout(() => self.#keepAliveTimerElapsed(), self.keepAliveInterval * 1000); //console.log("Keep Alive Received " + self.jitter); @@ -3489,7 +3500,7 @@ export default class DistributedConnection extends IStore { if (r == null) { let id = self.#attachedResources.keys[i]; // send detach - self.#sendDetachRequest(id); + self._sendDetachRequest(id); toBeRemoved.push(id); } } @@ -3520,7 +3531,7 @@ export default class DistributedConnection extends IStore { this.#requests.add(c, reply); - this.this.#sendParams() + this.#sendParams() .addUint8(0x40 | IIPPacketAction.StaticCall) .addUint32(c) .addGuid(classId) @@ -3577,7 +3588,7 @@ export default class DistributedConnection extends IStore { jitter = Math.abs(diff - interval); } - this.this.#sendParams() + this.#sendParams() .addUint8(0x80 | IIPPacketAction.KeepAlive) .addUint32(callbackId) .addDateTime(now) diff --git a/src/Net/IIP/DistributedResource.js b/src/Net/IIP/DistributedResource.js index 419e503..044530c 100644 --- a/src/Net/IIP/DistributedResource.js +++ b/src/Net/IIP/DistributedResource.js @@ -45,7 +45,7 @@ export default class DistributedResource extends IResource { this._p.destroyed = true; this._p.attached = false; - this._p.connection.detachResource(this._p.instanceId); + this._p.connection._sendDetachRequest(this._p.instanceId); this._emit("destroy", this); } @@ -297,20 +297,17 @@ export default class DistributedResource extends IResource if (this._p.properties[index] == value) return null; - var reply = new AsyncReply(); + let reply = new AsyncReply(); - var parameters = Codec.compose(value, this._p.connection); - var self = this; + let self = this; - this._p.connection._sendRequest(IIPPacketAction.SetProperty) - .addUint32(self._p.instanceId).addUint8(index).addUint8Array(parameters) - .done() - .then(function(res) - { - // not really needed, server will always send property modified, this only happens if the programmer forgot to emit in property setter - self._p.properties[index] = value; - reply.trigger(null); - }); + this._p.connection._sendSetProperty(self._p.instanceId, index, value) + .then(function(res) + { + // not really needed, server will always send property modified, this only happens if the programmer forgot to emit in property setter + //self._p.properties[index] = value; + reply.trigger(null); + }); return reply; } diff --git a/src/Net/Packets/IIPAuthPacket.js b/src/Net/Packets/IIPAuthPacket.js index 1c5fc0e..4734e85 100644 --- a/src/Net/Packets/IIPAuthPacket.js +++ b/src/Net/Packets/IIPAuthPacket.js @@ -27,9 +27,10 @@ "use strict"; +import AuthenticationMethod from "../../Security/Authority/AuthenticationMethod.js"; import IIPAuthPacketCommand from "./IIPAuthPacketCommand.js"; import IIPAuthPacketAction from "./IIPAuthPacketAction.js"; -import AuthenticationMethod from "../../Security/Authority/AuthenticationMethod.js"; +import IIPAuthPacketEvent from "./IIPAuthPacketEvent.js"; import TransmissionType from '../../Data/TransmissionType.js'; export default class IIPAuthPacket @@ -117,7 +118,7 @@ export default class IIPAuthPacket this.dataType = parsed.type; offset += parsed.size; - } else if (command == IIPAuthPacketCommand.Action) { + } else if (this.command == IIPAuthPacketCommand.Action) { this.action = (data[offset++]); @@ -140,7 +141,7 @@ export default class IIPAuthPacket this.challenge = data.clip(offset, hashLength); offset += hashLength; - } else if (action == IIPAuthPacketAction.AuthenticatePrivateHashCert || + } else if (this.action == IIPAuthPacketAction.AuthenticatePrivateHashCert || this.action == IIPAuthPacketAction.AuthenticatePublicPrivateHashCert) { if (this.#notEnough(offset, ends, 3)) @@ -170,7 +171,7 @@ export default class IIPAuthPacket offset += certLength; - } else if (action == IIPAuthPacketAction.IAuthPlain) { + } else if (this.action == IIPAuthPacketAction.IAuthPlain) { if (this.#notEnough(offset, ends, 5)) return -this.#dataLengthNeeded; @@ -186,7 +187,7 @@ export default class IIPAuthPacket this.dataType = parsed.type; offset += parsed.size; - } else if (action == IIPAuthPacketAction.IAuthHashed) { + } else if (this.action == IIPAuthPacketAction.IAuthHashed) { if (this.#notEnough(offset, ends, 7)) return -this.#dataLengthNeeded; @@ -206,7 +207,7 @@ export default class IIPAuthPacket offset += cl; - } else if (action == IIPAuthPacketAction.IAuthEncrypted) { + } else if (this.action == IIPAuthPacketAction.IAuthEncrypted) { if (this.#notEnough(offset, ends, 7)) return -this.#dataLengthNeeded; @@ -226,9 +227,9 @@ export default class IIPAuthPacket offset += cl; - } else if (action == IIPAuthPacketAction.EstablishNewSession) { + } else if (this.action == IIPAuthPacketAction.EstablishNewSession) { // Nothing here - } else if (action == IIPAuthPacketAction.EstablishResumeSession) { + } else if (this.action == IIPAuthPacketAction.EstablishResumeSession) { if (this.#notEnough(offset, ends, 1)) return -this.#dataLengthNeeded; @@ -242,7 +243,7 @@ export default class IIPAuthPacket offset += sessionLength; - } else if (action == IIPAuthPacketAction.EncryptKeyExchange) { + } else if (this.action == IIPAuthPacketAction.EncryptKeyExchange) { if (this.#notEnough(offset, ends, 2)) return -this.#dataLengthNeeded; @@ -258,7 +259,7 @@ export default class IIPAuthPacket offset += keyLength; - } else if (action == IIPAuthPacketAction.RegisterEndToEndKey || + } else if (this.action == IIPAuthPacketAction.RegisterEndToEndKey || this.action == IIPAuthPacketAction.RegisterHomomorphic) { if (this.#notEnough(offset, ends, 3)) @@ -278,7 +279,7 @@ export default class IIPAuthPacket offset += keyLength; } - } else if (command == IIPAuthPacketCommand.Event) { + } else if (this.command == IIPAuthPacketCommand.Event) { this.event = data[offset++]; diff --git a/src/Net/Packets/IIPAuthPacketIAuthHeader.js b/src/Net/Packets/IIPAuthPacketIAuthHeader.js index 82b9e84..f580e48 100644 --- a/src/Net/Packets/IIPAuthPacketIAuthHeader.js +++ b/src/Net/Packets/IIPAuthPacketIAuthHeader.js @@ -1,11 +1,16 @@ + +import { UInt8 } from "../../Data/ExtendedTypes.js"; + // IIPAuthPacketIAuthHeader export default { - Reference: 0, - Destination: 1, - Clue: 2, - RequiredFormat: 3, - ContentFormat: 4, - Content: 5, - Timeout: 6 + Reference: new UInt8(0), + Destination: new UInt8(1), + Clue: new UInt8(2), + RequiredFormat: new UInt8(3), + ContentFormat: new UInt8(4), + Content: new UInt8(5), + Trials: new UInt8(6), + Issue: new UInt8(7), + Expire: new UInt8(8) } \ No newline at end of file diff --git a/src/Security/Membership/AuthorizationRequest.js b/src/Security/Membership/AuthorizationRequest.js new file mode 100644 index 0000000..23f439e --- /dev/null +++ b/src/Security/Membership/AuthorizationRequest.js @@ -0,0 +1,52 @@ + +//AuthorizationResults +import IIPAuthPacketIAuthHeader from '../../Net/Packets/IIPAuthPacketIAuthHeader.js'; + +export default class AuthorizationRequest { + reference; + destination; + clue; + requiredFormat; + contentFormat; + content; + trials; + issue = new Date(); + expire; + + get expired (){ + return new Date() > this.expire; + } + + get timeout() { + if (this.expire != null) + return (this.expire - new Date()) / 1000; + else + return 30; + } + + constructor(headers){ + this.reference = headers.get(IIPAuthPacketIAuthHeader.Reference); + this.destination = headers.get(IIPAuthPacketIAuthHeader.Destination); + this.clue = headers.get(IIPAuthPacketIAuthHeader.Clue); + + if (headers.has(IIPAuthPacketIAuthHeader.RequiredFormat)) + requiredFormat = headers.get(IIPAuthPacketIAuthHeader.RequiredFormat); + + if (headers.has(IIPAuthPacketIAuthHeader.ContentFormat)) + contentFormat = headers.get(IIPAuthPacketIAuthHeader.ContentFormat); + + if (headers.has(IIPAuthPacketIAuthHeader.Content)) + content = headers.get(IIPAuthPacketIAuthHeader.Content); + + if (headers.has(IIPAuthPacketIAuthHeader.Trials)) + trials = headers.get(IIPAuthPacketIAuthHeader.Trials); + + if (headers.has(IIPAuthPacketIAuthHeader.Issue)) + this.issue = headers.get(IIPAuthPacketIAuthHeader.Issue); + + if (headers.has(IIPAuthPacketIAuthHeader.Expire)) + expire = headers.get(IIPAuthPacketIAuthHeader.Expire); + + } +} + diff --git a/src/Security/Membership/AuthorizationResults.js b/src/Security/Membership/AuthorizationResults.js index f2b8299..ea94aca 100644 --- a/src/Security/Membership/AuthorizationResults.js +++ b/src/Security/Membership/AuthorizationResults.js @@ -1,19 +1,33 @@ //AuthorizationResults -export default class { - response; - destination; - requiredFormat; - clue; - - timeout; // 0 means no timeout - reference; - - issue = new Date(); +import AuthorizationResultsResponse from './AuthorizationResultsResponse.js'; +export default class AuthorizationResults { + response = AuthorizationResultsResponse.Failed; + reference; + destination; + clue; + requiredFormat; + contentFormat; + content; + trials; + issue = new Date(); + expire; + get expired (){ - this.timeout == 0 ? false : ((new Date() - this.issue) / 1000) > this.timeout; - } + return new Date() > this.expire; + } + + get timeout() { + if (this.expire != null) + return (this.expire - new Date()) / 1000; + else + return 30; + } + + constructor(response = AuthorizationResultsResponse.Failed){ + this.response = response; + } } diff --git a/src/Security/Membership/AuthorizationResultsResponse.js b/src/Security/Membership/AuthorizationResultsResponse.js new file mode 100644 index 0000000..5874a4b --- /dev/null +++ b/src/Security/Membership/AuthorizationResultsResponse.js @@ -0,0 +1,10 @@ +// AuthorizationResultsResponse +export default { + Success: 0, + Failed: 1, + Expired: 2, + ServiceUnavailable: 3, + IAuthPlain: 4, + IAuthHashed: 5, + IAuthEncrypted: 6 +} \ No newline at end of file diff --git a/src/Security/Membership/IMembership.js b/src/Security/Membership/IMembership.js index b6370ee..d28e44f 100644 --- a/src/Security/Membership/IMembership.js +++ b/src/Security/Membership/IMembership.js @@ -1,5 +1,6 @@ import AsyncReply from "../../Core/AsyncReply.js"; import IResource from "../../Resource/IResource.js"; +import AuthorizationResults from '../../Security/Membership/AuthorizationResults.js'; export default class IMembership extends IResource {